LLVM  9.0.0svn
WebAssemblyISelLowering.cpp
Go to the documentation of this file.
1 //=- WebAssemblyISelLowering.cpp - WebAssembly DAG Lowering 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 implements the WebAssemblyTargetLowering class.
11 ///
12 //===----------------------------------------------------------------------===//
13 
17 #include "WebAssemblySubtarget.h"
19 #include "llvm/CodeGen/Analysis.h"
27 #include "llvm/IR/DiagnosticInfo.h"
29 #include "llvm/IR/Function.h"
30 #include "llvm/IR/Intrinsics.h"
31 #include "llvm/Support/Debug.h"
35 using namespace llvm;
36 
37 #define DEBUG_TYPE "wasm-lower"
38 
40  const TargetMachine &TM, const WebAssemblySubtarget &STI)
41  : TargetLowering(TM), Subtarget(&STI) {
42  auto MVTPtr = Subtarget->hasAddr64() ? MVT::i64 : MVT::i32;
43 
44  // Booleans always contain 0 or 1.
46  // Except in SIMD vectors
48  // WebAssembly does not produce floating-point exceptions on normal floating
49  // point operations.
51  // We don't know the microarchitecture here, so just reduce register pressure.
53  // Tell ISel that we have a stack pointer.
55  Subtarget->hasAddr64() ? WebAssembly::SP64 : WebAssembly::SP32);
56  // Set up the register classes.
57  addRegisterClass(MVT::i32, &WebAssembly::I32RegClass);
58  addRegisterClass(MVT::i64, &WebAssembly::I64RegClass);
59  addRegisterClass(MVT::f32, &WebAssembly::F32RegClass);
60  addRegisterClass(MVT::f64, &WebAssembly::F64RegClass);
61  if (Subtarget->hasSIMD128()) {
62  addRegisterClass(MVT::v16i8, &WebAssembly::V128RegClass);
63  addRegisterClass(MVT::v8i16, &WebAssembly::V128RegClass);
64  addRegisterClass(MVT::v4i32, &WebAssembly::V128RegClass);
65  addRegisterClass(MVT::v4f32, &WebAssembly::V128RegClass);
66  }
67  if (Subtarget->hasUnimplementedSIMD128()) {
68  addRegisterClass(MVT::v2i64, &WebAssembly::V128RegClass);
69  addRegisterClass(MVT::v2f64, &WebAssembly::V128RegClass);
70  }
71  // Compute derived properties from the register classes.
73 
79 
80  // Take the default expansion for va_arg, va_copy, and va_end. There is no
81  // default action for va_start, so we do that custom.
86 
87  for (auto T : {MVT::f32, MVT::f64, MVT::v4f32, MVT::v2f64}) {
88  // Don't expand the floating-point types to constant pools.
90  // Expand floating-point comparisons.
91  for (auto CC : {ISD::SETO, ISD::SETUO, ISD::SETUEQ, ISD::SETONE,
94  // Expand floating-point library function operators.
95  for (auto Op :
98  // Note supported floating-point library function operators that otherwise
99  // default to expand.
100  for (auto Op :
103  // Support minimum and maximum, which otherwise default to expand.
106  // WebAssembly currently has no builtin f16 support.
111  }
112 
113  // Expand unavailable integer operations.
114  for (auto Op :
118  for (auto T : {MVT::i32, MVT::i64})
120  if (Subtarget->hasSIMD128())
121  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
123  if (Subtarget->hasUnimplementedSIMD128())
125  }
126 
127  // SIMD-specific configuration
128  if (Subtarget->hasSIMD128()) {
129  // Support saturating add for i8x16 and i16x8
130  for (auto Op : {ISD::SADDSAT, ISD::UADDSAT})
131  for (auto T : {MVT::v16i8, MVT::v8i16})
133 
134  // Custom lower BUILD_VECTORs to minimize number of replace_lanes
135  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32})
137  if (Subtarget->hasUnimplementedSIMD128())
138  for (auto T : {MVT::v2i64, MVT::v2f64})
140 
141  // We have custom shuffle lowering to expose the shuffle mask
142  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32})
144  if (Subtarget->hasUnimplementedSIMD128())
145  for (auto T: {MVT::v2i64, MVT::v2f64})
147 
148  // Custom lowering since wasm shifts must have a scalar shift amount
149  for (auto Op : {ISD::SHL, ISD::SRA, ISD::SRL}) {
150  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
152  if (Subtarget->hasUnimplementedSIMD128())
154  }
155 
156  // Custom lower lane accesses to expand out variable indices
158  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32})
160  if (Subtarget->hasUnimplementedSIMD128())
161  for (auto T : {MVT::v2i64, MVT::v2f64})
163  }
164 
165  // There is no i64x2.mul instruction
167 
168  // There are no vector select instructions
169  for (auto Op : {ISD::VSELECT, ISD::SELECT_CC, ISD::SELECT}) {
170  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32})
172  if (Subtarget->hasUnimplementedSIMD128())
173  for (auto T : {MVT::v2i64, MVT::v2f64})
175  }
176 
177  // Expand integer operations supported for scalars but not SIMD
180  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
182  if (Subtarget->hasUnimplementedSIMD128())
184  }
185 
186  // Expand float operations supported for scalars but not SIMD
188  ISD::FCOPYSIGN}) {
190  if (Subtarget->hasUnimplementedSIMD128())
192  }
193 
194  // Expand additional SIMD ops that V8 hasn't implemented yet
195  if (!Subtarget->hasUnimplementedSIMD128()) {
198  }
199  }
200 
201  // As a special case, these operators use the type to mean the type to
202  // sign-extend from.
204  if (!Subtarget->hasSignExt()) {
205  // Sign extends are legal only when extending a vector extract
206  auto Action = Subtarget->hasSIMD128() ? Custom : Expand;
207  for (auto T : {MVT::i8, MVT::i16, MVT::i32})
209  }
210  for (auto T : MVT::integer_vector_valuetypes())
212 
213  // Dynamic stack allocation: use the default expansion.
217 
220 
221  // Expand these forms; we pattern-match the forms that we can handle in isel.
222  for (auto T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
223  for (auto Op : {ISD::BR_CC, ISD::SELECT_CC})
225 
226  // We have custom switch handling.
228 
229  // WebAssembly doesn't have:
230  // - Floating-point extending loads.
231  // - Floating-point truncating stores.
232  // - i1 extending loads.
233  // - extending/truncating SIMD loads/stores
236  for (auto T : MVT::integer_valuetypes())
239  if (Subtarget->hasSIMD128()) {
241  MVT::v2f64}) {
242  for (auto MemT : MVT::vector_valuetypes()) {
243  if (MVT(T) != MemT) {
244  setTruncStoreAction(T, MemT, Expand);
246  setLoadExtAction(Ext, T, MemT, Expand);
247  }
248  }
249  }
250  }
251 
252  // Don't do anything clever with build_pairs
254 
255  // Trap lowers to wasm unreachable
257 
258  // Exception handling intrinsics
261 
263 
264  if (Subtarget->hasBulkMemory()) {
265  // Use memory.copy and friends over multiple loads and stores
266  MaxStoresPerMemcpy = 1;
270  MaxStoresPerMemset = 1;
272  }
273 }
274 
276 WebAssemblyTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
277  // We have wasm instructions for these
278  switch (AI->getOperation()) {
279  case AtomicRMWInst::Add:
280  case AtomicRMWInst::Sub:
281  case AtomicRMWInst::And:
282  case AtomicRMWInst::Or:
283  case AtomicRMWInst::Xor:
284  case AtomicRMWInst::Xchg:
286  default:
287  break;
288  }
290 }
291 
292 FastISel *WebAssemblyTargetLowering::createFastISel(
293  FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo) const {
294  return WebAssembly::createFastISel(FuncInfo, LibInfo);
295 }
296 
297 MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
298  EVT VT) const {
299  unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1);
300  if (BitWidth > 1 && BitWidth < 8)
301  BitWidth = 8;
302 
303  if (BitWidth > 64) {
304  // The shift will be lowered to a libcall, and compiler-rt libcalls expect
305  // the count to be an i32.
306  BitWidth = 32;
307  assert(BitWidth >= Log2_32_Ceil(VT.getSizeInBits()) &&
308  "32-bit shift counts ought to be enough for anyone");
309  }
310 
311  MVT Result = MVT::getIntegerVT(BitWidth);
313  "Unable to represent scalar shift amount type");
314  return Result;
315 }
316 
317 // Lower an fp-to-int conversion operator from the LLVM opcode, which has an
318 // undefined result on invalid/overflow, to the WebAssembly opcode, which
319 // traps on invalid/overflow.
321  MachineBasicBlock *BB,
322  const TargetInstrInfo &TII,
323  bool IsUnsigned, bool Int64,
324  bool Float64, unsigned LoweredOpcode) {
326 
327  unsigned OutReg = MI.getOperand(0).getReg();
328  unsigned InReg = MI.getOperand(1).getReg();
329 
330  unsigned Abs = Float64 ? WebAssembly::ABS_F64 : WebAssembly::ABS_F32;
331  unsigned FConst = Float64 ? WebAssembly::CONST_F64 : WebAssembly::CONST_F32;
332  unsigned LT = Float64 ? WebAssembly::LT_F64 : WebAssembly::LT_F32;
333  unsigned GE = Float64 ? WebAssembly::GE_F64 : WebAssembly::GE_F32;
334  unsigned IConst = Int64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32;
335  unsigned Eqz = WebAssembly::EQZ_I32;
336  unsigned And = WebAssembly::AND_I32;
337  int64_t Limit = Int64 ? INT64_MIN : INT32_MIN;
338  int64_t Substitute = IsUnsigned ? 0 : Limit;
339  double CmpVal = IsUnsigned ? -(double)Limit * 2.0 : -(double)Limit;
340  auto &Context = BB->getParent()->getFunction().getContext();
342 
343  const BasicBlock *LLVMBB = BB->getBasicBlock();
344  MachineFunction *F = BB->getParent();
345  MachineBasicBlock *TrueMBB = F->CreateMachineBasicBlock(LLVMBB);
346  MachineBasicBlock *FalseMBB = F->CreateMachineBasicBlock(LLVMBB);
347  MachineBasicBlock *DoneMBB = F->CreateMachineBasicBlock(LLVMBB);
348 
350  F->insert(It, FalseMBB);
351  F->insert(It, TrueMBB);
352  F->insert(It, DoneMBB);
353 
354  // Transfer the remainder of BB and its successor edges to DoneMBB.
355  DoneMBB->splice(DoneMBB->begin(), BB, std::next(MI.getIterator()), BB->end());
356  DoneMBB->transferSuccessorsAndUpdatePHIs(BB);
357 
358  BB->addSuccessor(TrueMBB);
359  BB->addSuccessor(FalseMBB);
360  TrueMBB->addSuccessor(DoneMBB);
361  FalseMBB->addSuccessor(DoneMBB);
362 
363  unsigned Tmp0, Tmp1, CmpReg, EqzReg, FalseReg, TrueReg;
364  Tmp0 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
365  Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
366  CmpReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
367  EqzReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
368  FalseReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
369  TrueReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
370 
371  MI.eraseFromParent();
372  // For signed numbers, we can do a single comparison to determine whether
373  // fabs(x) is within range.
374  if (IsUnsigned) {
375  Tmp0 = InReg;
376  } else {
377  BuildMI(BB, DL, TII.get(Abs), Tmp0).addReg(InReg);
378  }
379  BuildMI(BB, DL, TII.get(FConst), Tmp1)
380  .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, CmpVal)));
381  BuildMI(BB, DL, TII.get(LT), CmpReg).addReg(Tmp0).addReg(Tmp1);
382 
383  // For unsigned numbers, we have to do a separate comparison with zero.
384  if (IsUnsigned) {
385  Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
386  unsigned SecondCmpReg =
387  MRI.createVirtualRegister(&WebAssembly::I32RegClass);
388  unsigned AndReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
389  BuildMI(BB, DL, TII.get(FConst), Tmp1)
390  .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, 0.0)));
391  BuildMI(BB, DL, TII.get(GE), SecondCmpReg).addReg(Tmp0).addReg(Tmp1);
392  BuildMI(BB, DL, TII.get(And), AndReg).addReg(CmpReg).addReg(SecondCmpReg);
393  CmpReg = AndReg;
394  }
395 
396  BuildMI(BB, DL, TII.get(Eqz), EqzReg).addReg(CmpReg);
397 
398  // Create the CFG diamond to select between doing the conversion or using
399  // the substitute value.
400  BuildMI(BB, DL, TII.get(WebAssembly::BR_IF)).addMBB(TrueMBB).addReg(EqzReg);
401  BuildMI(FalseMBB, DL, TII.get(LoweredOpcode), FalseReg).addReg(InReg);
402  BuildMI(FalseMBB, DL, TII.get(WebAssembly::BR)).addMBB(DoneMBB);
403  BuildMI(TrueMBB, DL, TII.get(IConst), TrueReg).addImm(Substitute);
404  BuildMI(*DoneMBB, DoneMBB->begin(), DL, TII.get(TargetOpcode::PHI), OutReg)
405  .addReg(FalseReg)
406  .addMBB(FalseMBB)
407  .addReg(TrueReg)
408  .addMBB(TrueMBB);
409 
410  return DoneMBB;
411 }
412 
413 MachineBasicBlock *WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
414  MachineInstr &MI, MachineBasicBlock *BB) const {
415  const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
416  DebugLoc DL = MI.getDebugLoc();
417 
418  switch (MI.getOpcode()) {
419  default:
420  llvm_unreachable("Unexpected instr type to insert");
421  case WebAssembly::FP_TO_SINT_I32_F32:
422  return LowerFPToInt(MI, DL, BB, TII, false, false, false,
423  WebAssembly::I32_TRUNC_S_F32);
424  case WebAssembly::FP_TO_UINT_I32_F32:
425  return LowerFPToInt(MI, DL, BB, TII, true, false, false,
426  WebAssembly::I32_TRUNC_U_F32);
427  case WebAssembly::FP_TO_SINT_I64_F32:
428  return LowerFPToInt(MI, DL, BB, TII, false, true, false,
429  WebAssembly::I64_TRUNC_S_F32);
430  case WebAssembly::FP_TO_UINT_I64_F32:
431  return LowerFPToInt(MI, DL, BB, TII, true, true, false,
432  WebAssembly::I64_TRUNC_U_F32);
433  case WebAssembly::FP_TO_SINT_I32_F64:
434  return LowerFPToInt(MI, DL, BB, TII, false, false, true,
435  WebAssembly::I32_TRUNC_S_F64);
436  case WebAssembly::FP_TO_UINT_I32_F64:
437  return LowerFPToInt(MI, DL, BB, TII, true, false, true,
438  WebAssembly::I32_TRUNC_U_F64);
439  case WebAssembly::FP_TO_SINT_I64_F64:
440  return LowerFPToInt(MI, DL, BB, TII, false, true, true,
441  WebAssembly::I64_TRUNC_S_F64);
442  case WebAssembly::FP_TO_UINT_I64_F64:
443  return LowerFPToInt(MI, DL, BB, TII, true, true, true,
444  WebAssembly::I64_TRUNC_U_F64);
445  llvm_unreachable("Unexpected instruction to emit with custom inserter");
446  }
447 }
448 
449 const char *
450 WebAssemblyTargetLowering::getTargetNodeName(unsigned Opcode) const {
451  switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) {
453  break;
454 #define HANDLE_NODETYPE(NODE) \
455  case WebAssemblyISD::NODE: \
456  return "WebAssemblyISD::" #NODE;
457 #include "WebAssemblyISD.def"
458 #undef HANDLE_NODETYPE
459  }
460  return nullptr;
461 }
462 
463 std::pair<unsigned, const TargetRegisterClass *>
464 WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
465  const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
466  // First, see if this is a constraint that directly corresponds to a
467  // WebAssembly register class.
468  if (Constraint.size() == 1) {
469  switch (Constraint[0]) {
470  case 'r':
471  assert(VT != MVT::iPTR && "Pointer MVT not expected here");
472  if (Subtarget->hasSIMD128() && VT.isVector()) {
473  if (VT.getSizeInBits() == 128)
474  return std::make_pair(0U, &WebAssembly::V128RegClass);
475  }
476  if (VT.isInteger() && !VT.isVector()) {
477  if (VT.getSizeInBits() <= 32)
478  return std::make_pair(0U, &WebAssembly::I32RegClass);
479  if (VT.getSizeInBits() <= 64)
480  return std::make_pair(0U, &WebAssembly::I64RegClass);
481  }
482  break;
483  default:
484  break;
485  }
486  }
487 
488  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
489 }
490 
491 bool WebAssemblyTargetLowering::isCheapToSpeculateCttz() const {
492  // Assume ctz is a relatively cheap operation.
493  return true;
494 }
495 
496 bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz() const {
497  // Assume clz is a relatively cheap operation.
498  return true;
499 }
500 
501 bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
502  const AddrMode &AM,
503  Type *Ty, unsigned AS,
504  Instruction *I) const {
505  // WebAssembly offsets are added as unsigned without wrapping. The
506  // isLegalAddressingMode gives us no way to determine if wrapping could be
507  // happening, so we approximate this by accepting only non-negative offsets.
508  if (AM.BaseOffs < 0)
509  return false;
510 
511  // WebAssembly has no scale register operands.
512  if (AM.Scale != 0)
513  return false;
514 
515  // Everything else is legal.
516  return true;
517 }
518 
519 bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses(
520  EVT /*VT*/, unsigned /*AddrSpace*/, unsigned /*Align*/, bool *Fast) const {
521  // WebAssembly supports unaligned accesses, though it should be declared
522  // with the p2align attribute on loads and stores which do so, and there
523  // may be a performance impact. We tell LLVM they're "fast" because
524  // for the kinds of things that LLVM uses this for (merging adjacent stores
525  // of constants, etc.), WebAssembly implementations will either want the
526  // unaligned access or they'll split anyway.
527  if (Fast)
528  *Fast = true;
529  return true;
530 }
531 
532 bool WebAssemblyTargetLowering::isIntDivCheap(EVT VT,
533  AttributeList Attr) const {
534  // The current thinking is that wasm engines will perform this optimization,
535  // so we can save on code size.
536  return true;
537 }
538 
539 EVT WebAssemblyTargetLowering::getSetCCResultType(const DataLayout &DL,
540  LLVMContext &C,
541  EVT VT) const {
542  if (VT.isVector())
544 
545  return TargetLowering::getSetCCResultType(DL, C, VT);
546 }
547 
548 bool WebAssemblyTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
549  const CallInst &I,
550  MachineFunction &MF,
551  unsigned Intrinsic) const {
552  switch (Intrinsic) {
553  case Intrinsic::wasm_atomic_notify:
555  Info.memVT = MVT::i32;
556  Info.ptrVal = I.getArgOperand(0);
557  Info.offset = 0;
558  Info.align = 4;
559  // atomic.notify instruction does not really load the memory specified with
560  // this argument, but MachineMemOperand should either be load or store, so
561  // we set this to a load.
562  // FIXME Volatile isn't really correct, but currently all LLVM atomic
563  // instructions are treated as volatiles in the backend, so we should be
564  // consistent. The same applies for wasm_atomic_wait intrinsics too.
566  return true;
567  case Intrinsic::wasm_atomic_wait_i32:
569  Info.memVT = MVT::i32;
570  Info.ptrVal = I.getArgOperand(0);
571  Info.offset = 0;
572  Info.align = 4;
574  return true;
575  case Intrinsic::wasm_atomic_wait_i64:
577  Info.memVT = MVT::i64;
578  Info.ptrVal = I.getArgOperand(0);
579  Info.offset = 0;
580  Info.align = 8;
582  return true;
583  default:
584  return false;
585  }
586 }
587 
588 //===----------------------------------------------------------------------===//
589 // WebAssembly Lowering private implementation.
590 //===----------------------------------------------------------------------===//
591 
592 //===----------------------------------------------------------------------===//
593 // Lowering Code
594 //===----------------------------------------------------------------------===//
595 
596 static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *Msg) {
598  DAG.getContext()->diagnose(
600 }
601 
602 // Test whether the given calling convention is supported.
603 static bool callingConvSupported(CallingConv::ID CallConv) {
604  // We currently support the language-independent target-independent
605  // conventions. We don't yet have a way to annotate calls with properties like
606  // "cold", and we don't have any call-clobbered registers, so these are mostly
607  // all handled the same.
608  return CallConv == CallingConv::C || CallConv == CallingConv::Fast ||
609  CallConv == CallingConv::Cold ||
610  CallConv == CallingConv::PreserveMost ||
611  CallConv == CallingConv::PreserveAll ||
612  CallConv == CallingConv::CXX_FAST_TLS;
613 }
614 
615 SDValue
616 WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
617  SmallVectorImpl<SDValue> &InVals) const {
618  SelectionDAG &DAG = CLI.DAG;
619  SDLoc DL = CLI.DL;
620  SDValue Chain = CLI.Chain;
621  SDValue Callee = CLI.Callee;
623  auto Layout = MF.getDataLayout();
624 
625  CallingConv::ID CallConv = CLI.CallConv;
626  if (!callingConvSupported(CallConv))
627  fail(DL, DAG,
628  "WebAssembly doesn't support language-specific or target-specific "
629  "calling conventions yet");
630  if (CLI.IsPatchPoint)
631  fail(DL, DAG, "WebAssembly doesn't support patch point yet");
632 
633  // WebAssembly doesn't currently support explicit tail calls. If they are
634  // required, fail. Otherwise, just disable them.
635  if ((CallConv == CallingConv::Fast && CLI.IsTailCall &&
637  (CLI.CS && CLI.CS.isMustTailCall()))
638  fail(DL, DAG, "WebAssembly doesn't support tail call yet");
639  CLI.IsTailCall = false;
640 
642  if (Ins.size() > 1)
643  fail(DL, DAG, "WebAssembly doesn't support more than 1 returned value yet");
644 
645  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
646  SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
647  unsigned NumFixedArgs = 0;
648  for (unsigned I = 0; I < Outs.size(); ++I) {
649  const ISD::OutputArg &Out = Outs[I];
650  SDValue &OutVal = OutVals[I];
651  if (Out.Flags.isNest())
652  fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
653  if (Out.Flags.isInAlloca())
654  fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
655  if (Out.Flags.isInConsecutiveRegs())
656  fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
657  if (Out.Flags.isInConsecutiveRegsLast())
658  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
659  if (Out.Flags.isByVal() && Out.Flags.getByValSize() != 0) {
660  auto &MFI = MF.getFrameInfo();
661  int FI = MFI.CreateStackObject(Out.Flags.getByValSize(),
662  Out.Flags.getByValAlign(),
663  /*isSS=*/false);
664  SDValue SizeNode =
665  DAG.getConstant(Out.Flags.getByValSize(), DL, MVT::i32);
666  SDValue FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
667  Chain = DAG.getMemcpy(
668  Chain, DL, FINode, OutVal, SizeNode, Out.Flags.getByValAlign(),
669  /*isVolatile*/ false, /*AlwaysInline=*/false,
670  /*isTailCall*/ false, MachinePointerInfo(), MachinePointerInfo());
671  OutVal = FINode;
672  }
673  // Count the number of fixed args *after* legalization.
674  NumFixedArgs += Out.IsFixed;
675  }
676 
677  bool IsVarArg = CLI.IsVarArg;
678  auto PtrVT = getPointerTy(Layout);
679 
680  // Analyze operands of the call, assigning locations to each operand.
682  CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
683 
684  if (IsVarArg) {
685  // Outgoing non-fixed arguments are placed in a buffer. First
686  // compute their offsets and the total amount of buffer space needed.
687  for (unsigned I = NumFixedArgs; I < Outs.size(); ++I) {
688  const ISD::OutputArg &Out = Outs[I];
689  SDValue &Arg = OutVals[I];
690  EVT VT = Arg.getValueType();
691  assert(VT != MVT::iPTR && "Legalized args should be concrete");
692  Type *Ty = VT.getTypeForEVT(*DAG.getContext());
693  unsigned Align = std::max(Out.Flags.getOrigAlign(),
694  Layout.getABITypeAlignment(Ty));
695  unsigned Offset = CCInfo.AllocateStack(Layout.getTypeAllocSize(Ty),
696  Align);
697  CCInfo.addLoc(CCValAssign::getMem(ArgLocs.size(), VT.getSimpleVT(),
698  Offset, VT.getSimpleVT(),
700  }
701  }
702 
703  unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
704 
705  SDValue FINode;
706  if (IsVarArg && NumBytes) {
707  // For non-fixed arguments, next emit stores to store the argument values
708  // to the stack buffer at the offsets computed above.
709  int FI = MF.getFrameInfo().CreateStackObject(NumBytes,
710  Layout.getStackAlignment(),
711  /*isSS=*/false);
712  unsigned ValNo = 0;
714  for (SDValue Arg :
715  make_range(OutVals.begin() + NumFixedArgs, OutVals.end())) {
716  assert(ArgLocs[ValNo].getValNo() == ValNo &&
717  "ArgLocs should remain in order and only hold varargs args");
718  unsigned Offset = ArgLocs[ValNo++].getLocMemOffset();
719  FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
720  SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, FINode,
721  DAG.getConstant(Offset, DL, PtrVT));
722  Chains.push_back(
723  DAG.getStore(Chain, DL, Arg, Add,
724  MachinePointerInfo::getFixedStack(MF, FI, Offset), 0));
725  }
726  if (!Chains.empty())
727  Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
728  } else if (IsVarArg) {
729  FINode = DAG.getIntPtrConstant(0, DL);
730  }
731 
732  if (Callee->getOpcode() == ISD::GlobalAddress) {
733  // If the callee is a GlobalAddress node (quite common, every direct call
734  // is) turn it into a TargetGlobalAddress node so that LowerGlobalAddress
735  // doesn't at MO_GOT which is not needed for direct calls.
736  GlobalAddressSDNode* GA = cast<GlobalAddressSDNode>(Callee);
737  Callee = DAG.getTargetGlobalAddress(GA->getGlobal(), DL,
739  GA->getOffset());
740  Callee = DAG.getNode(WebAssemblyISD::Wrapper, DL,
741  getPointerTy(DAG.getDataLayout()), Callee);
742  }
743 
744  // Compute the operands for the CALLn node.
746  Ops.push_back(Chain);
747  Ops.push_back(Callee);
748 
749  // Add all fixed arguments. Note that for non-varargs calls, NumFixedArgs
750  // isn't reliable.
751  Ops.append(OutVals.begin(),
752  IsVarArg ? OutVals.begin() + NumFixedArgs : OutVals.end());
753  // Add a pointer to the vararg buffer.
754  if (IsVarArg)
755  Ops.push_back(FINode);
756 
757  SmallVector<EVT, 8> InTys;
758  for (const auto &In : Ins) {
759  assert(!In.Flags.isByVal() && "byval is not valid for return values");
760  assert(!In.Flags.isNest() && "nest is not valid for return values");
761  if (In.Flags.isInAlloca())
762  fail(DL, DAG, "WebAssembly hasn't implemented inalloca return values");
763  if (In.Flags.isInConsecutiveRegs())
764  fail(DL, DAG, "WebAssembly hasn't implemented cons regs return values");
765  if (In.Flags.isInConsecutiveRegsLast())
766  fail(DL, DAG,
767  "WebAssembly hasn't implemented cons regs last return values");
768  // Ignore In.getOrigAlign() because all our arguments are passed in
769  // registers.
770  InTys.push_back(In.VT);
771  }
772  InTys.push_back(MVT::Other);
773  SDVTList InTyList = DAG.getVTList(InTys);
774  SDValue Res =
775  DAG.getNode(Ins.empty() ? WebAssemblyISD::CALL0 : WebAssemblyISD::CALL1,
776  DL, InTyList, Ops);
777  if (Ins.empty()) {
778  Chain = Res;
779  } else {
780  InVals.push_back(Res);
781  Chain = Res.getValue(1);
782  }
783 
784  return Chain;
785 }
786 
787 bool WebAssemblyTargetLowering::CanLowerReturn(
788  CallingConv::ID /*CallConv*/, MachineFunction & /*MF*/, bool /*IsVarArg*/,
790  LLVMContext & /*Context*/) const {
791  // WebAssembly can't currently handle returning tuples.
792  return Outs.size() <= 1;
793 }
794 
795 SDValue WebAssemblyTargetLowering::LowerReturn(
796  SDValue Chain, CallingConv::ID CallConv, bool /*IsVarArg*/,
798  const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
799  SelectionDAG &DAG) const {
800  assert(Outs.size() <= 1 && "WebAssembly can only return up to one value");
801  if (!callingConvSupported(CallConv))
802  fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
803 
804  SmallVector<SDValue, 4> RetOps(1, Chain);
805  RetOps.append(OutVals.begin(), OutVals.end());
806  Chain = DAG.getNode(WebAssemblyISD::RETURN, DL, MVT::Other, RetOps);
807 
808  // Record the number and types of the return values.
809  for (const ISD::OutputArg &Out : Outs) {
810  assert(!Out.Flags.isByVal() && "byval is not valid for return values");
811  assert(!Out.Flags.isNest() && "nest is not valid for return values");
812  assert(Out.IsFixed && "non-fixed return value is not valid");
813  if (Out.Flags.isInAlloca())
814  fail(DL, DAG, "WebAssembly hasn't implemented inalloca results");
815  if (Out.Flags.isInConsecutiveRegs())
816  fail(DL, DAG, "WebAssembly hasn't implemented cons regs results");
817  if (Out.Flags.isInConsecutiveRegsLast())
818  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last results");
819  }
820 
821  return Chain;
822 }
823 
824 SDValue WebAssemblyTargetLowering::LowerFormalArguments(
825  SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
826  const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
827  SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
828  if (!callingConvSupported(CallConv))
829  fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
830 
832  auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
833 
834  // Set up the incoming ARGUMENTS value, which serves to represent the liveness
835  // of the incoming values before they're represented by virtual registers.
836  MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
837 
838  for (const ISD::InputArg &In : Ins) {
839  if (In.Flags.isInAlloca())
840  fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
841  if (In.Flags.isNest())
842  fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
843  if (In.Flags.isInConsecutiveRegs())
844  fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
845  if (In.Flags.isInConsecutiveRegsLast())
846  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
847  // Ignore In.getOrigAlign() because all our arguments are passed in
848  // registers.
849  InVals.push_back(In.Used ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
850  DAG.getTargetConstant(InVals.size(),
851  DL, MVT::i32))
852  : DAG.getUNDEF(In.VT));
853 
854  // Record the number and types of arguments.
855  MFI->addParam(In.VT);
856  }
857 
858  // Varargs are copied into a buffer allocated by the caller, and a pointer to
859  // the buffer is passed as an argument.
860  if (IsVarArg) {
861  MVT PtrVT = getPointerTy(MF.getDataLayout());
862  unsigned VarargVreg =
864  MFI->setVarargBufferVreg(VarargVreg);
865  Chain = DAG.getCopyToReg(
866  Chain, DL, VarargVreg,
867  DAG.getNode(WebAssemblyISD::ARGUMENT, DL, PtrVT,
868  DAG.getTargetConstant(Ins.size(), DL, MVT::i32)));
869  MFI->addParam(PtrVT);
870  }
871 
872  // Record the number and types of arguments and results.
873  SmallVector<MVT, 4> Params;
876  DAG.getTarget(), Params, Results);
877  for (MVT VT : Results)
878  MFI->addResult(VT);
879  // TODO: Use signatures in WebAssemblyMachineFunctionInfo too and unify
880  // the param logic here with ComputeSignatureVTs
881  assert(MFI->getParams().size() == Params.size() &&
882  std::equal(MFI->getParams().begin(), MFI->getParams().end(),
883  Params.begin()));
884 
885  return Chain;
886 }
887 
888 //===----------------------------------------------------------------------===//
889 // Custom lowering hooks.
890 //===----------------------------------------------------------------------===//
891 
892 SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
893  SelectionDAG &DAG) const {
894  SDLoc DL(Op);
895  switch (Op.getOpcode()) {
896  default:
897  llvm_unreachable("unimplemented operation lowering");
898  return SDValue();
899  case ISD::FrameIndex:
900  return LowerFrameIndex(Op, DAG);
901  case ISD::GlobalAddress:
902  return LowerGlobalAddress(Op, DAG);
903  case ISD::ExternalSymbol:
904  return LowerExternalSymbol(Op, DAG);
905  case ISD::JumpTable:
906  return LowerJumpTable(Op, DAG);
907  case ISD::BR_JT:
908  return LowerBR_JT(Op, DAG);
909  case ISD::VASTART:
910  return LowerVASTART(Op, DAG);
911  case ISD::BlockAddress:
912  case ISD::BRIND:
913  fail(DL, DAG, "WebAssembly hasn't implemented computed gotos");
914  return SDValue();
915  case ISD::RETURNADDR: // Probably nothing meaningful can be returned here.
916  fail(DL, DAG, "WebAssembly hasn't implemented __builtin_return_address");
917  return SDValue();
918  case ISD::FRAMEADDR:
919  return LowerFRAMEADDR(Op, DAG);
920  case ISD::CopyToReg:
921  return LowerCopyToReg(Op, DAG);
924  return LowerAccessVectorElement(Op, DAG);
925  case ISD::INTRINSIC_VOID:
928  return LowerIntrinsic(Op, DAG);
930  return LowerSIGN_EXTEND_INREG(Op, DAG);
931  case ISD::BUILD_VECTOR:
932  return LowerBUILD_VECTOR(Op, DAG);
933  case ISD::VECTOR_SHUFFLE:
934  return LowerVECTOR_SHUFFLE(Op, DAG);
935  case ISD::SHL:
936  case ISD::SRA:
937  case ISD::SRL:
938  return LowerShift(Op, DAG);
939  }
940 }
941 
942 SDValue WebAssemblyTargetLowering::LowerCopyToReg(SDValue Op,
943  SelectionDAG &DAG) const {
944  SDValue Src = Op.getOperand(2);
945  if (isa<FrameIndexSDNode>(Src.getNode())) {
946  // CopyToReg nodes don't support FrameIndex operands. Other targets select
947  // the FI to some LEA-like instruction, but since we don't have that, we
948  // need to insert some kind of instruction that can take an FI operand and
949  // produces a value usable by CopyToReg (i.e. in a vreg). So insert a dummy
950  // local.copy between Op and its FI operand.
951  SDValue Chain = Op.getOperand(0);
952  SDLoc DL(Op);
953  unsigned Reg = cast<RegisterSDNode>(Op.getOperand(1))->getReg();
954  EVT VT = Src.getValueType();
955  SDValue Copy(DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32
956  : WebAssembly::COPY_I64,
957  DL, VT, Src),
958  0);
959  return Op.getNode()->getNumValues() == 1
960  ? DAG.getCopyToReg(Chain, DL, Reg, Copy)
961  : DAG.getCopyToReg(Chain, DL, Reg, Copy,
962  Op.getNumOperands() == 4 ? Op.getOperand(3)
963  : SDValue());
964  }
965  return SDValue();
966 }
967 
968 SDValue WebAssemblyTargetLowering::LowerFrameIndex(SDValue Op,
969  SelectionDAG &DAG) const {
970  int FI = cast<FrameIndexSDNode>(Op)->getIndex();
971  return DAG.getTargetFrameIndex(FI, Op.getValueType());
972 }
973 
974 SDValue WebAssemblyTargetLowering::LowerFRAMEADDR(SDValue Op,
975  SelectionDAG &DAG) const {
976  // Non-zero depths are not supported by WebAssembly currently. Use the
977  // legalizer's default expansion, which is to return 0 (what this function is
978  // documented to do).
979  if (Op.getConstantOperandVal(0) > 0)
980  return SDValue();
981 
983  EVT VT = Op.getValueType();
984  unsigned FP =
986  return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), FP, VT);
987 }
988 
989 SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
990  SelectionDAG &DAG) const {
991  SDLoc DL(Op);
992  const auto *GA = cast<GlobalAddressSDNode>(Op);
993  EVT VT = Op.getValueType();
994  assert(GA->getTargetFlags() == 0 &&
995  "Unexpected target flags on generic GlobalAddressSDNode");
996  if (GA->getAddressSpace() != 0)
997  fail(DL, DAG, "WebAssembly only expects the 0 address space");
998 
999  unsigned OperandFlags = 0;
1000  if (isPositionIndependent()) {
1001  const GlobalValue *GV = GA->getGlobal();
1002  if (getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV)) {
1003  MachineFunction &MF = DAG.getMachineFunction();
1004  MVT PtrVT = getPointerTy(MF.getDataLayout());
1005  const char *BaseName;
1006  if (GV->getValueType()->isFunctionTy()) {
1007  BaseName = MF.createExternalSymbolName("__table_base");
1008  OperandFlags = WebAssemblyII::MO_TABLE_BASE_REL;
1009  }
1010  else {
1011  BaseName = MF.createExternalSymbolName("__memory_base");
1012  OperandFlags = WebAssemblyII::MO_MEMORY_BASE_REL;
1013  }
1014  SDValue BaseAddr =
1015  DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT,
1016  DAG.getTargetExternalSymbol(BaseName, PtrVT));
1017 
1018  SDValue SymAddr = DAG.getNode(
1020  DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset(),
1021  OperandFlags));
1022 
1023  return DAG.getNode(ISD::ADD, DL, VT, BaseAddr, SymAddr);
1024  } else {
1025  OperandFlags = WebAssemblyII::MO_GOT;
1026  }
1027  }
1028 
1029  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1030  DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT,
1031  GA->getOffset(), OperandFlags));
1032 }
1033 
1034 SDValue
1035 WebAssemblyTargetLowering::LowerExternalSymbol(SDValue Op,
1036  SelectionDAG &DAG) const {
1037  SDLoc DL(Op);
1038  const auto *ES = cast<ExternalSymbolSDNode>(Op);
1039  EVT VT = Op.getValueType();
1040  assert(ES->getTargetFlags() == 0 &&
1041  "Unexpected target flags on generic ExternalSymbolSDNode");
1042  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1043  DAG.getTargetExternalSymbol(ES->getSymbol(), VT));
1044 }
1045 
1046 SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op,
1047  SelectionDAG &DAG) const {
1048  // There's no need for a Wrapper node because we always incorporate a jump
1049  // table operand into a BR_TABLE instruction, rather than ever
1050  // materializing it in a register.
1051  const JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
1052  return DAG.getTargetJumpTable(JT->getIndex(), Op.getValueType(),
1053  JT->getTargetFlags());
1054 }
1055 
1056 SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op,
1057  SelectionDAG &DAG) const {
1058  SDLoc DL(Op);
1059  SDValue Chain = Op.getOperand(0);
1060  const auto *JT = cast<JumpTableSDNode>(Op.getOperand(1));
1061  SDValue Index = Op.getOperand(2);
1062  assert(JT->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");
1063 
1065  Ops.push_back(Chain);
1066  Ops.push_back(Index);
1067 
1069  const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs;
1070 
1071  // Add an operand for each case.
1072  for (auto MBB : MBBs)
1073  Ops.push_back(DAG.getBasicBlock(MBB));
1074 
1075  // TODO: For now, we just pick something arbitrary for a default case for now.
1076  // We really want to sniff out the guard and put in the real default case (and
1077  // delete the guard).
1078  Ops.push_back(DAG.getBasicBlock(MBBs[0]));
1079 
1080  return DAG.getNode(WebAssemblyISD::BR_TABLE, DL, MVT::Other, Ops);
1081 }
1082 
1083 SDValue WebAssemblyTargetLowering::LowerVASTART(SDValue Op,
1084  SelectionDAG &DAG) const {
1085  SDLoc DL(Op);
1087 
1088  auto *MFI = DAG.getMachineFunction().getInfo<WebAssemblyFunctionInfo>();
1089  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
1090 
1091  SDValue ArgN = DAG.getCopyFromReg(DAG.getEntryNode(), DL,
1092  MFI->getVarargBufferVreg(), PtrVT);
1093  return DAG.getStore(Op.getOperand(0), DL, ArgN, Op.getOperand(1),
1094  MachinePointerInfo(SV), 0);
1095 }
1096 
1097 SDValue WebAssemblyTargetLowering::LowerIntrinsic(SDValue Op,
1098  SelectionDAG &DAG) const {
1099  MachineFunction &MF = DAG.getMachineFunction();
1100  unsigned IntNo;
1101  switch (Op.getOpcode()) {
1102  case ISD::INTRINSIC_VOID:
1104  IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
1105  break;
1107  IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
1108  break;
1109  default:
1110  llvm_unreachable("Invalid intrinsic");
1111  }
1112  SDLoc DL(Op);
1113 
1114  switch (IntNo) {
1115  default:
1116  return SDValue(); // Don't custom lower most intrinsics.
1117 
1118  case Intrinsic::wasm_lsda: {
1119  EVT VT = Op.getValueType();
1120  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1121  MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
1122  auto &Context = MF.getMMI().getContext();
1123  MCSymbol *S = Context.getOrCreateSymbol(Twine("GCC_except_table") +
1124  Twine(MF.getFunctionNumber()));
1125  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1126  DAG.getMCSymbol(S, PtrVT));
1127  }
1128 
1129  case Intrinsic::wasm_throw: {
1130  // We only support C++ exceptions for now
1131  int Tag = cast<ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue();
1132  if (Tag != CPP_EXCEPTION)
1133  llvm_unreachable("Invalid tag!");
1134  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1135  MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
1136  const char *SymName = MF.createExternalSymbolName("__cpp_exception");
1137  SDValue SymNode = DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT,
1138  DAG.getTargetExternalSymbol(SymName, PtrVT));
1139  return DAG.getNode(WebAssemblyISD::THROW, DL,
1140  MVT::Other, // outchain type
1141  {
1142  Op.getOperand(0), // inchain
1143  SymNode, // exception symbol
1144  Op.getOperand(3) // thrown value
1145  });
1146  }
1147  }
1148 }
1149 
1150 SDValue
1151 WebAssemblyTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
1152  SelectionDAG &DAG) const {
1153  // If sign extension operations are disabled, allow sext_inreg only if operand
1154  // is a vector extract. SIMD does not depend on sign extension operations, but
1155  // allowing sext_inreg in this context lets us have simple patterns to select
1156  // extract_lane_s instructions. Expanding sext_inreg everywhere would be
1157  // simpler in this file, but would necessitate large and brittle patterns to
1158  // undo the expansion and select extract_lane_s instructions.
1159  assert(!Subtarget->hasSignExt() && Subtarget->hasSIMD128());
1161  return Op;
1162  // Otherwise expand
1163  return SDValue();
1164 }
1165 
1166 SDValue WebAssemblyTargetLowering::LowerBUILD_VECTOR(SDValue Op,
1167  SelectionDAG &DAG) const {
1168  SDLoc DL(Op);
1169  const EVT VecT = Op.getValueType();
1170  const EVT LaneT = Op.getOperand(0).getValueType();
1171  const size_t Lanes = Op.getNumOperands();
1172  auto IsConstant = [](const SDValue &V) {
1173  return V.getOpcode() == ISD::Constant || V.getOpcode() == ISD::ConstantFP;
1174  };
1175 
1176  // Find the most common operand, which is approximately the best to splat
1177  using Entry = std::pair<SDValue, size_t>;
1178  SmallVector<Entry, 16> ValueCounts;
1179  size_t NumConst = 0, NumDynamic = 0;
1180  for (const SDValue &Lane : Op->op_values()) {
1181  if (Lane.isUndef()) {
1182  continue;
1183  } else if (IsConstant(Lane)) {
1184  NumConst++;
1185  } else {
1186  NumDynamic++;
1187  }
1188  auto CountIt = std::find_if(ValueCounts.begin(), ValueCounts.end(),
1189  [&Lane](Entry A) { return A.first == Lane; });
1190  if (CountIt == ValueCounts.end()) {
1191  ValueCounts.emplace_back(Lane, 1);
1192  } else {
1193  CountIt->second++;
1194  }
1195  }
1196  auto CommonIt =
1197  std::max_element(ValueCounts.begin(), ValueCounts.end(),
1198  [](Entry A, Entry B) { return A.second < B.second; });
1199  assert(CommonIt != ValueCounts.end() && "Unexpected all-undef build_vector");
1200  SDValue SplatValue = CommonIt->first;
1201  size_t NumCommon = CommonIt->second;
1202 
1203  // If v128.const is available, consider using it instead of a splat
1204  if (Subtarget->hasUnimplementedSIMD128()) {
1205  // {i32,i64,f32,f64}.const opcode, and value
1206  const size_t ConstBytes = 1 + std::max(size_t(4), 16 / Lanes);
1207  // SIMD prefix and opcode
1208  const size_t SplatBytes = 2;
1209  const size_t SplatConstBytes = SplatBytes + ConstBytes;
1210  // SIMD prefix, opcode, and lane index
1211  const size_t ReplaceBytes = 3;
1212  const size_t ReplaceConstBytes = ReplaceBytes + ConstBytes;
1213  // SIMD prefix, v128.const opcode, and 128-bit value
1214  const size_t VecConstBytes = 18;
1215  // Initial v128.const and a replace_lane for each non-const operand
1216  const size_t ConstInitBytes = VecConstBytes + NumDynamic * ReplaceBytes;
1217  // Initial splat and all necessary replace_lanes
1218  const size_t SplatInitBytes =
1219  IsConstant(SplatValue)
1220  // Initial constant splat
1221  ? (SplatConstBytes +
1222  // Constant replace_lanes
1223  (NumConst - NumCommon) * ReplaceConstBytes +
1224  // Dynamic replace_lanes
1225  (NumDynamic * ReplaceBytes))
1226  // Initial dynamic splat
1227  : (SplatBytes +
1228  // Constant replace_lanes
1229  (NumConst * ReplaceConstBytes) +
1230  // Dynamic replace_lanes
1231  (NumDynamic - NumCommon) * ReplaceBytes);
1232  if (ConstInitBytes < SplatInitBytes) {
1233  // Create build_vector that will lower to initial v128.const
1234  SmallVector<SDValue, 16> ConstLanes;
1235  for (const SDValue &Lane : Op->op_values()) {
1236  if (IsConstant(Lane)) {
1237  ConstLanes.push_back(Lane);
1238  } else if (LaneT.isFloatingPoint()) {
1239  ConstLanes.push_back(DAG.getConstantFP(0, DL, LaneT));
1240  } else {
1241  ConstLanes.push_back(DAG.getConstant(0, DL, LaneT));
1242  }
1243  }
1244  SDValue Result = DAG.getBuildVector(VecT, DL, ConstLanes);
1245  // Add replace_lane instructions for non-const lanes
1246  for (size_t I = 0; I < Lanes; ++I) {
1247  const SDValue &Lane = Op->getOperand(I);
1248  if (!Lane.isUndef() && !IsConstant(Lane))
1249  Result = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VecT, Result, Lane,
1250  DAG.getConstant(I, DL, MVT::i32));
1251  }
1252  return Result;
1253  }
1254  }
1255  // Use a splat for the initial vector
1256  SDValue Result = DAG.getSplatBuildVector(VecT, DL, SplatValue);
1257  // Add replace_lane instructions for other values
1258  for (size_t I = 0; I < Lanes; ++I) {
1259  const SDValue &Lane = Op->getOperand(I);
1260  if (Lane != SplatValue)
1261  Result = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VecT, Result, Lane,
1262  DAG.getConstant(I, DL, MVT::i32));
1263  }
1264  return Result;
1265 }
1266 
1267 SDValue
1268 WebAssemblyTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
1269  SelectionDAG &DAG) const {
1270  SDLoc DL(Op);
1271  ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(Op.getNode())->getMask();
1273  assert(VecType.is128BitVector() && "Unexpected shuffle vector type");
1274  size_t LaneBytes = VecType.getVectorElementType().getSizeInBits() / 8;
1275 
1276  // Space for two vector args and sixteen mask indices
1277  SDValue Ops[18];
1278  size_t OpIdx = 0;
1279  Ops[OpIdx++] = Op.getOperand(0);
1280  Ops[OpIdx++] = Op.getOperand(1);
1281 
1282  // Expand mask indices to byte indices and materialize them as operands
1283  for (int M : Mask) {
1284  for (size_t J = 0; J < LaneBytes; ++J) {
1285  // Lower undefs (represented by -1 in mask) to zero
1286  uint64_t ByteIndex = M == -1 ? 0 : (uint64_t)M * LaneBytes + J;
1287  Ops[OpIdx++] = DAG.getConstant(ByteIndex, DL, MVT::i32);
1288  }
1289  }
1290 
1291  return DAG.getNode(WebAssemblyISD::SHUFFLE, DL, Op.getValueType(), Ops);
1292 }
1293 
1294 SDValue
1295 WebAssemblyTargetLowering::LowerAccessVectorElement(SDValue Op,
1296  SelectionDAG &DAG) const {
1297  // Allow constant lane indices, expand variable lane indices
1298  SDNode *IdxNode = Op.getOperand(Op.getNumOperands() - 1).getNode();
1299  if (isa<ConstantSDNode>(IdxNode) || IdxNode->isUndef())
1300  return Op;
1301  else
1302  // Perform default expansion
1303  return SDValue();
1304 }
1305 
1308  // 32-bit and 64-bit unrolled shifts will have proper semantics
1309  if (LaneT.bitsGE(MVT::i32))
1310  return DAG.UnrollVectorOp(Op.getNode());
1311  // Otherwise mask the shift value to get proper semantics from 32-bit shift
1312  SDLoc DL(Op);
1313  SDValue ShiftVal = Op.getOperand(1);
1314  uint64_t MaskVal = LaneT.getSizeInBits() - 1;
1315  SDValue MaskedShiftVal = DAG.getNode(
1316  ISD::AND, // mask opcode
1317  DL, ShiftVal.getValueType(), // masked value type
1318  ShiftVal, // original shift value operand
1319  DAG.getConstant(MaskVal, DL, ShiftVal.getValueType()) // mask operand
1320  );
1321 
1322  return DAG.UnrollVectorOp(
1323  DAG.getNode(Op.getOpcode(), // original shift opcode
1324  DL, Op.getValueType(), // original return type
1325  Op.getOperand(0), // original vector operand,
1326  MaskedShiftVal // new masked shift value operand
1327  )
1328  .getNode());
1329 }
1330 
1331 SDValue WebAssemblyTargetLowering::LowerShift(SDValue Op,
1332  SelectionDAG &DAG) const {
1333  SDLoc DL(Op);
1334 
1335  // Only manually lower vector shifts
1337 
1338  // Expand all vector shifts until V8 fixes its implementation
1339  // TODO: remove this once V8 is fixed
1340  if (!Subtarget->hasUnimplementedSIMD128())
1341  return unrollVectorShift(Op, DAG);
1342 
1343  // Unroll non-splat vector shifts
1344  BuildVectorSDNode *ShiftVec;
1345  SDValue SplatVal;
1346  if (!(ShiftVec = dyn_cast<BuildVectorSDNode>(Op.getOperand(1).getNode())) ||
1347  !(SplatVal = ShiftVec->getSplatValue()))
1348  return unrollVectorShift(Op, DAG);
1349 
1350  // All splats except i64x2 const splats are handled by patterns
1351  auto *SplatConst = dyn_cast<ConstantSDNode>(SplatVal);
1352  if (!SplatConst || Op.getSimpleValueType() != MVT::v2i64)
1353  return Op;
1354 
1355  // i64x2 const splats are custom lowered to avoid unnecessary wraps
1356  unsigned Opcode;
1357  switch (Op.getOpcode()) {
1358  case ISD::SHL:
1359  Opcode = WebAssemblyISD::VEC_SHL;
1360  break;
1361  case ISD::SRA:
1362  Opcode = WebAssemblyISD::VEC_SHR_S;
1363  break;
1364  case ISD::SRL:
1365  Opcode = WebAssemblyISD::VEC_SHR_U;
1366  break;
1367  default:
1368  llvm_unreachable("unexpected opcode");
1369  }
1370  APInt Shift = SplatConst->getAPIntValue().zextOrTrunc(32);
1371  return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(0),
1372  DAG.getConstant(Shift, DL, MVT::i32));
1373 }
1374 
1375 //===----------------------------------------------------------------------===//
1376 // WebAssembly Optimization Hooks
1377 //===----------------------------------------------------------------------===//
SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, unsigned Alignment=0, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
void setFrameAddressIsTaken(bool T)
uint64_t CallInst * C
static MVT getIntegerVT(unsigned BitWidth)
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
Definition: MathExtras.h:551
This file defines the interfaces that WebAssembly uses to lower LLVM code into a selection DAG...
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:110
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:645
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
EVT getValueType() const
Return the ValueType of the referenced return value.
bool isInteger() const
Return true if this is an integer or a vector integer type.
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
static Type * getDoubleTy(LLVMContext &C)
Definition: Type.cpp:164
bool isUndef() const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
const GlobalValue * getGlobal() const
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
LLVMContext & Context
Diagnostic information for unsupported feature in backend.
SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
const TargetRegisterClass * getRegClass(unsigned Reg) const
Return the register class of the specified virtual register.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
BR_CC - Conditional branch.
Definition: ISDOpcodes.h:651
This class represents lattice values for constants.
Definition: AllocatorList.h:23
InputArg - This struct carries flags and type information about a single incoming (formal) argument o...
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0...
Definition: ISDOpcodes.h:606
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition: ISDOpcodes.h:366
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
bool isVector() const
Return true if this is a vector value type.
void addLiveIn(unsigned Reg, unsigned vreg=0)
addLiveIn - Add the specified register as a live-in.
Carry-setting nodes for multiple precision addition and subtraction.
Definition: ISDOpcodes.h:222
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:382
unsigned getReg() const
getReg - Returns the register number.
void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain...
Definition: ISDOpcodes.h:703
This class represents a function call, abstracting a target machine&#39;s calling convention.
unsigned Reg
void setHasFloatingPointExceptions(bool FPExceptions=true)
Tells the code generator that this target supports floating point exceptions and cares about preservi...
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition: ValueTypes.h:252
SDValue getBasicBlock(MachineBasicBlock *MBB)
Function Alias Analysis Results
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
virtual const TargetRegisterClass * getRegClassFor(MVT VT) const
Return the register class that should be used for the specified value type.
unsigned const TargetRegisterInfo * TRI
A debug info location.
Definition: DebugLoc.h:33
F(f)
MachineModuleInfo & getMMI() const
APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
Definition: APInt.cpp:875
an instruction that atomically reads a memory location, combines it with another value, and then stores the result back.
Definition: Instructions.h:691
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned char TargetFlags=0)
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
C - The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
void computeSignatureVTs(const FunctionType *Ty, const Function &F, const TargetMachine &TM, SmallVectorImpl< MVT > &Params, SmallVectorImpl< MVT > &Results)
int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it...
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition: ISDOpcodes.h:434
SDValue getMCSymbol(MCSymbol *Sym, EVT VT)
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition: ISDOpcodes.h:158
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
Definition: ISDOpcodes.h:209
Value * getArgOperand(unsigned i) const
Definition: InstrTypes.h:1155
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition: ValueTypes.h:135
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations...
Definition: ISDOpcodes.h:455
SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
const HexagonInstrInfo * TII
static Type * getFloatTy(LLVMContext &C)
Definition: Type.cpp:163
#define INT64_MIN
Definition: DataTypes.h:80
Shift and rotation operations.
Definition: ISDOpcodes.h:409
Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
Definition: ValueTypes.cpp:205
MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s), MachineInstr opcode, and operands.
BinOp getOperation() const
Definition: Instructions.h:750
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
Definition: ISDOpcodes.h:190
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:41
void eraseFromParent()
Unlink &#39;this&#39; from the containing basic block and delete it.
CopyToReg - This node has three operands: a chain, a register number to set to this value...
Definition: ISDOpcodes.h:169
uint64_t getConstantOperandVal(unsigned i) const
void setCondCodeAction(ISD::CondCode CC, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn&#39;t supported on the target and indicate what to d...
bool isInConsecutiveRegs() const
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:408
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
Definition: SelectionDAG.h:462
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
const DataLayout & getDataLayout() const
Definition: SelectionDAG.h:403
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG...
Definition: ISDOpcodes.h:72
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
OutputArg - This struct carries flags and a value for a single outgoing (actual) argument or outgoing...
This represents a list of ValueType&#39;s that has been intern&#39;d by a SelectionDAG.
STACKSAVE - STACKSAVE has one operand, an input chain.
Definition: ISDOpcodes.h:699
unsigned getSizeInBits() const
This is a fast-path instruction selection class that generates poor code and doesn&#39;t support illegal ...
Definition: FastISel.h:66
unsigned getSizeInBits() const
Return the size of the specified value type in bits.
Definition: ValueTypes.h:291
This file declares the WebAssembly-specific subclass of TargetMachine.
MachineFunction & getMachineFunction() const
Definition: SelectionDAG.h:400
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose...
SDValue getTargetFrameIndex(int FI, EVT VT)
Definition: SelectionDAG.h:633
const TargetMachine & getTarget() const
Definition: SelectionDAG.h:404
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition: ISDOpcodes.h:428
const MCContext & getContext() const
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:200
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:32
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:130
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
Definition: SelectionDAG.h:857
static mvt_range integer_vector_valuetypes()
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
Definition: SelectionDAG.h:581
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements. ...
Definition: SelectionDAG.h:756
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition: ISDOpcodes.h:150
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *bb=nullptr)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
MVT getVectorElementType() const
Analysis containing CSE Info
Definition: CSEInfo.cpp:20
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
unsigned getByValSize() const
bool IsFixed
IsFixed - Is this a "fixed" value, ie not passed through a vararg "...".
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a vector with the specified, possibly variable...
Definition: ISDOpcodes.h:326
TargetInstrInfo - Interface to description of machine instruction set.
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
static SDValue unrollVectorShift(SDValue Op, SelectionDAG &DAG)
bool is128BitVector() const
Return true if this is a 128-bit vector type.
The memory access is volatile.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
Definition: ValueTypes.h:234
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition: ISDOpcodes.h:165
Control flow instructions. These all have token chains.
Definition: ISDOpcodes.h:630
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
unsigned const MachineRegisterInfo * MRI
MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
Machine Value Type.
LLVM Basic Block Representation.
Definition: BasicBlock.h:57
unsigned getOrigAlign() const
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:64
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type...
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE...
Definition: ISDOpcodes.h:732
iterator_range< value_op_iterator > op_values() const
const SDValue & getOperand(unsigned Num) const
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL...
Definition: ISDOpcodes.h:331
Carry-using nodes for multiple precision addition and subtraction.
Definition: ISDOpcodes.h:231
OperandFlags
These are flags set on operands, but should be considered private, all access should go through the M...
Definition: MCInstrDesc.h:40
This file provides WebAssembly-specific target descriptions.
unsigned char getTargetFlags() const
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
TRAP - Trapping instruction.
Definition: ISDOpcodes.h:771
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline...
static mvt_range vector_valuetypes()
self_iterator getIterator()
Definition: ilist_node.h:81
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
Definition: ISDOpcodes.h:723
auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1213
unsigned MaxStoresPerMemmove
Specify maximum bytes of store instructions per memmove call.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:192
static unsigned NumFixedArgs
Extended Value Type.
Definition: ValueTypes.h:33
uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
Definition: MathExtras.h:639
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
bool isPositionIndependent() const
size_t size() const
Definition: SmallVector.h:52
const TargetMachine & getTargetMachine() const
This class contains a discriminated union of information about pointers in memory operands...
const char * createExternalSymbolName(StringRef Name)
Allocate a string and populate it with the given external symbol name.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
SDValue getSplatValue(const APInt &DemandedElts, BitVector *UndefElements=nullptr) const
Returns the demanded splatted value or a null value if this is not a splat.
WebAssemblyTargetLowering(const TargetMachine &TM, const WebAssemblySubtarget &STI)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition: ISDOpcodes.h:264
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned char TargetFlags=0)
Definition: SelectionDAG.h:638
TokenFactor - This node takes multiple tokens as input and produces a single token result...
Definition: ISDOpcodes.h:49
static MachineBasicBlock * LowerFPToInt(MachineInstr &MI, DebugLoc DL, MachineBasicBlock *BB, const TargetInstrInfo &TII, bool IsUnsigned, bool Int64, bool Float64, unsigned LoweredOpcode)
This file declares the WebAssembly-specific subclass of TargetSubtarget.
const TargetLowering & getTargetLoweringInfo() const
Definition: SelectionDAG.h:406
Iterator for intrusive lists based on ilist_node.
CCState - This class holds information needed while lowering arguments and return values...
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition: ISDOpcodes.h:338
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:221
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:841
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
Definition: SelectionDAG.h:739
Provides information about what library functions are available for the current target.
const DebugLoc & getDebugLoc() const
SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVol, bool AlwaysInline, bool isTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo)
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
Definition: ValueTypes.h:95
Byte Swap and Counting operators.
Definition: ISDOpcodes.h:412
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
Definition: ISDOpcodes.h:580
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
static Constant * get(Type *Ty, double V)
This returns a ConstantFP, or a vector containing a splat of a ConstantFP, for the specified value in...
Definition: Constants.cpp:694
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, SDValue N)
Definition: SelectionDAG.h:684
const Function & getFunction() const
Return the LLVM function that this machine code represents.
static mvt_range integer_valuetypes()
unsigned getFrameRegister(const MachineFunction &MF) const override
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:163
Fast - This calling convention attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:42
Class for arbitrary precision integers.
Definition: APInt.h:69
unsigned getByValAlign() const
SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
amdgpu Simplify well known AMD library false FunctionCallee Callee
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
A "pseudo-class" with methods for operating on BUILD_VECTORs.
Select(COND, TRUEVAL, FALSEVAL).
Definition: ISDOpcodes.h:419
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition: ISDOpcodes.h:311
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:387
const WebAssemblyRegisterInfo * getRegisterInfo() const override
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
The memory access reads data.
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
BR_JT - Jumptable branch.
Definition: ISDOpcodes.h:639
Representation of each machine instruction.
Definition: MachineInstr.h:63
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer, a SRCVALUE for the destination, and a SRCVALUE for the source.
Definition: ISDOpcodes.h:728
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
bool isVector() const
Return true if this is a vector value type.
Definition: ValueTypes.h:150
bool isFunctionTy() const
True if this is an instance of FunctionType.
Definition: Type.h:214
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:386
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB &#39;Other&#39; at the position From, and insert it into this MBB right before &#39;...
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
Definition: SelectionDAG.h:710
static bool callingConvSupported(CallingConv::ID CallConv)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition: ISDOpcodes.h:205
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:55
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition: ISDOpcodes.h:485
bool isInConsecutiveRegsLast() const
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:44
virtual EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const
Return the ValueType of the result of SETCC operations.
TargetOptions Options
#define I(x, y, z)
Definition: MD5.cpp:58
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
This file declares WebAssembly-specific per-machine-function information.
unsigned MaxStoresPerMemmoveOptSize
Maximum number of store instructions that may be substituted for a call to memmove, used for functions with OptSize attribute.
unsigned MaxStoresPerMemcpyOptSize
Maximum number of store operations that may be substituted for a call to memcpy, used for functions w...
void setStackPointerRegisterToSaveRestore(unsigned R)
If set to a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save and restore.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:332
Type * getValueType() const
Definition: GlobalValue.h:275
static CCValAssign getMem(unsigned ValNo, MVT ValVT, unsigned Offset, MVT LocVT, LocInfo HTP)
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
unsigned getOpcode() const
FSINCOS - Compute both fsin and fcos as a single operation.
Definition: ISDOpcodes.h:609
SDValue getValue(unsigned R) const
unsigned MaxStoresPerMemcpy
Specify maximum bytes of store instructions per memcpy call.
void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void insert(iterator MBBI, MachineBasicBlock *MBB)
SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:565
LLVM Value Representation.
Definition: Value.h:72
FMA - Perform a * b + c with no intermediate rounding step.
Definition: ISDOpcodes.h:301
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E&#39;s largest value.
Definition: BitmaskEnum.h:80
bool isUndef() const
Return true if the type of the node type undefined.
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:65
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
unsigned MaxStoresPerMemsetOptSize
Maximum number of stores operations that may be substituted for the call to memset, used for functions with OptSize attribute.
const WebAssemblyInstrInfo * getInstrInfo() const override
unsigned getNumOperands() const
const SDValue & getOperand(unsigned i) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0) const
static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *Msg)
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:413
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
LLVMContext * getContext() const
Definition: SelectionDAG.h:409
unsigned createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned char TargetFlags=0)
Definition: SelectionDAG.h:627
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition: ISDOpcodes.h:379
BRIND - Indirect branch.
Definition: ISDOpcodes.h:635
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary...
Definition: ISDOpcodes.h:624