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  // We don't know the microarchitecture here, so just reduce register pressure.
50  // Tell ISel that we have a stack pointer.
52  Subtarget->hasAddr64() ? WebAssembly::SP64 : WebAssembly::SP32);
53  // Set up the register classes.
54  addRegisterClass(MVT::i32, &WebAssembly::I32RegClass);
55  addRegisterClass(MVT::i64, &WebAssembly::I64RegClass);
56  addRegisterClass(MVT::f32, &WebAssembly::F32RegClass);
57  addRegisterClass(MVT::f64, &WebAssembly::F64RegClass);
58  if (Subtarget->hasSIMD128()) {
59  addRegisterClass(MVT::v16i8, &WebAssembly::V128RegClass);
60  addRegisterClass(MVT::v8i16, &WebAssembly::V128RegClass);
61  addRegisterClass(MVT::v4i32, &WebAssembly::V128RegClass);
62  addRegisterClass(MVT::v4f32, &WebAssembly::V128RegClass);
63  }
64  if (Subtarget->hasUnimplementedSIMD128()) {
65  addRegisterClass(MVT::v2i64, &WebAssembly::V128RegClass);
66  addRegisterClass(MVT::v2f64, &WebAssembly::V128RegClass);
67  }
68  // Compute derived properties from the register classes.
70 
76 
77  // Take the default expansion for va_arg, va_copy, and va_end. There is no
78  // default action for va_start, so we do that custom.
83 
84  for (auto T : {MVT::f32, MVT::f64, MVT::v4f32, MVT::v2f64}) {
85  // Don't expand the floating-point types to constant pools.
87  // Expand floating-point comparisons.
88  for (auto CC : {ISD::SETO, ISD::SETUO, ISD::SETUEQ, ISD::SETONE,
91  // Expand floating-point library function operators.
92  for (auto Op :
95  // Note supported floating-point library function operators that otherwise
96  // default to expand.
97  for (auto Op :
100  // Support minimum and maximum, which otherwise default to expand.
103  // WebAssembly currently has no builtin f16 support.
108  }
109 
110  // Expand unavailable integer operations.
111  for (auto Op :
115  for (auto T : {MVT::i32, MVT::i64})
117  if (Subtarget->hasSIMD128())
118  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
120  if (Subtarget->hasUnimplementedSIMD128())
122  }
123 
124  // SIMD-specific configuration
125  if (Subtarget->hasSIMD128()) {
126  // Support saturating add for i8x16 and i16x8
127  for (auto Op : {ISD::SADDSAT, ISD::UADDSAT})
128  for (auto T : {MVT::v16i8, MVT::v8i16})
130 
131  // Custom lower BUILD_VECTORs to minimize number of replace_lanes
132  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32})
134  if (Subtarget->hasUnimplementedSIMD128())
135  for (auto T : {MVT::v2i64, MVT::v2f64})
137 
138  // We have custom shuffle lowering to expose the shuffle mask
139  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32})
141  if (Subtarget->hasUnimplementedSIMD128())
142  for (auto T: {MVT::v2i64, MVT::v2f64})
144 
145  // Custom lowering since wasm shifts must have a scalar shift amount
146  for (auto Op : {ISD::SHL, ISD::SRA, ISD::SRL}) {
147  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
149  if (Subtarget->hasUnimplementedSIMD128())
151  }
152 
153  // Custom lower lane accesses to expand out variable indices
155  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32})
157  if (Subtarget->hasUnimplementedSIMD128())
158  for (auto T : {MVT::v2i64, MVT::v2f64})
160  }
161 
162  // There is no i64x2.mul instruction
164 
165  // There are no vector select instructions
166  for (auto Op : {ISD::VSELECT, ISD::SELECT_CC, ISD::SELECT}) {
167  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32})
169  if (Subtarget->hasUnimplementedSIMD128())
170  for (auto T : {MVT::v2i64, MVT::v2f64})
172  }
173 
174  // Expand integer operations supported for scalars but not SIMD
177  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
179  if (Subtarget->hasUnimplementedSIMD128())
181  }
182 
183  // Expand float operations supported for scalars but not SIMD
185  ISD::FCOPYSIGN}) {
187  if (Subtarget->hasUnimplementedSIMD128())
189  }
190 
191  // Expand additional SIMD ops that V8 hasn't implemented yet
192  if (!Subtarget->hasUnimplementedSIMD128()) {
195  }
196  }
197 
198  // As a special case, these operators use the type to mean the type to
199  // sign-extend from.
201  if (!Subtarget->hasSignExt()) {
202  // Sign extends are legal only when extending a vector extract
203  auto Action = Subtarget->hasSIMD128() ? Custom : Expand;
204  for (auto T : {MVT::i8, MVT::i16, MVT::i32})
206  }
207  for (auto T : MVT::integer_vector_valuetypes())
209 
210  // Dynamic stack allocation: use the default expansion.
214 
217 
218  // Expand these forms; we pattern-match the forms that we can handle in isel.
219  for (auto T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
220  for (auto Op : {ISD::BR_CC, ISD::SELECT_CC})
222 
223  // We have custom switch handling.
225 
226  // WebAssembly doesn't have:
227  // - Floating-point extending loads.
228  // - Floating-point truncating stores.
229  // - i1 extending loads.
230  // - extending/truncating SIMD loads/stores
233  for (auto T : MVT::integer_valuetypes())
236  if (Subtarget->hasSIMD128()) {
238  MVT::v2f64}) {
239  for (auto MemT : MVT::vector_valuetypes()) {
240  if (MVT(T) != MemT) {
241  setTruncStoreAction(T, MemT, Expand);
243  setLoadExtAction(Ext, T, MemT, Expand);
244  }
245  }
246  }
247  }
248 
249  // Don't do anything clever with build_pairs
251 
252  // Trap lowers to wasm unreachable
254 
255  // Exception handling intrinsics
258 
260 
261  if (Subtarget->hasBulkMemory()) {
262  // Use memory.copy and friends over multiple loads and stores
263  MaxStoresPerMemcpy = 1;
267  MaxStoresPerMemset = 1;
269  }
270 
271  // Override the __gnu_f2h_ieee/__gnu_h2f_ieee names so that the f32 name is
272  // consistent with the f64 and f128 names.
273  setLibcallName(RTLIB::FPEXT_F16_F32, "__extendhfsf2");
274  setLibcallName(RTLIB::FPROUND_F32_F16, "__truncsfhf2");
275 
276  // Always convert switches to br_tables unless there is only one case, which
277  // is equivalent to a simple branch. This reduces code size for wasm, and we
278  // defer possible jump table optimizations to the VM.
280 }
281 
283 WebAssemblyTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
284  // We have wasm instructions for these
285  switch (AI->getOperation()) {
286  case AtomicRMWInst::Add:
287  case AtomicRMWInst::Sub:
288  case AtomicRMWInst::And:
289  case AtomicRMWInst::Or:
290  case AtomicRMWInst::Xor:
291  case AtomicRMWInst::Xchg:
293  default:
294  break;
295  }
297 }
298 
299 FastISel *WebAssemblyTargetLowering::createFastISel(
300  FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo) const {
301  return WebAssembly::createFastISel(FuncInfo, LibInfo);
302 }
303 
304 MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
305  EVT VT) const {
306  unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1);
307  if (BitWidth > 1 && BitWidth < 8)
308  BitWidth = 8;
309 
310  if (BitWidth > 64) {
311  // The shift will be lowered to a libcall, and compiler-rt libcalls expect
312  // the count to be an i32.
313  BitWidth = 32;
314  assert(BitWidth >= Log2_32_Ceil(VT.getSizeInBits()) &&
315  "32-bit shift counts ought to be enough for anyone");
316  }
317 
318  MVT Result = MVT::getIntegerVT(BitWidth);
320  "Unable to represent scalar shift amount type");
321  return Result;
322 }
323 
324 // Lower an fp-to-int conversion operator from the LLVM opcode, which has an
325 // undefined result on invalid/overflow, to the WebAssembly opcode, which
326 // traps on invalid/overflow.
328  MachineBasicBlock *BB,
329  const TargetInstrInfo &TII,
330  bool IsUnsigned, bool Int64,
331  bool Float64, unsigned LoweredOpcode) {
333 
334  unsigned OutReg = MI.getOperand(0).getReg();
335  unsigned InReg = MI.getOperand(1).getReg();
336 
337  unsigned Abs = Float64 ? WebAssembly::ABS_F64 : WebAssembly::ABS_F32;
338  unsigned FConst = Float64 ? WebAssembly::CONST_F64 : WebAssembly::CONST_F32;
339  unsigned LT = Float64 ? WebAssembly::LT_F64 : WebAssembly::LT_F32;
340  unsigned GE = Float64 ? WebAssembly::GE_F64 : WebAssembly::GE_F32;
341  unsigned IConst = Int64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32;
342  unsigned Eqz = WebAssembly::EQZ_I32;
343  unsigned And = WebAssembly::AND_I32;
344  int64_t Limit = Int64 ? INT64_MIN : INT32_MIN;
345  int64_t Substitute = IsUnsigned ? 0 : Limit;
346  double CmpVal = IsUnsigned ? -(double)Limit * 2.0 : -(double)Limit;
347  auto &Context = BB->getParent()->getFunction().getContext();
349 
350  const BasicBlock *LLVMBB = BB->getBasicBlock();
351  MachineFunction *F = BB->getParent();
352  MachineBasicBlock *TrueMBB = F->CreateMachineBasicBlock(LLVMBB);
353  MachineBasicBlock *FalseMBB = F->CreateMachineBasicBlock(LLVMBB);
354  MachineBasicBlock *DoneMBB = F->CreateMachineBasicBlock(LLVMBB);
355 
357  F->insert(It, FalseMBB);
358  F->insert(It, TrueMBB);
359  F->insert(It, DoneMBB);
360 
361  // Transfer the remainder of BB and its successor edges to DoneMBB.
362  DoneMBB->splice(DoneMBB->begin(), BB, std::next(MI.getIterator()), BB->end());
363  DoneMBB->transferSuccessorsAndUpdatePHIs(BB);
364 
365  BB->addSuccessor(TrueMBB);
366  BB->addSuccessor(FalseMBB);
367  TrueMBB->addSuccessor(DoneMBB);
368  FalseMBB->addSuccessor(DoneMBB);
369 
370  unsigned Tmp0, Tmp1, CmpReg, EqzReg, FalseReg, TrueReg;
371  Tmp0 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
372  Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
373  CmpReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
374  EqzReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
375  FalseReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
376  TrueReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
377 
378  MI.eraseFromParent();
379  // For signed numbers, we can do a single comparison to determine whether
380  // fabs(x) is within range.
381  if (IsUnsigned) {
382  Tmp0 = InReg;
383  } else {
384  BuildMI(BB, DL, TII.get(Abs), Tmp0).addReg(InReg);
385  }
386  BuildMI(BB, DL, TII.get(FConst), Tmp1)
387  .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, CmpVal)));
388  BuildMI(BB, DL, TII.get(LT), CmpReg).addReg(Tmp0).addReg(Tmp1);
389 
390  // For unsigned numbers, we have to do a separate comparison with zero.
391  if (IsUnsigned) {
392  Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
393  unsigned SecondCmpReg =
394  MRI.createVirtualRegister(&WebAssembly::I32RegClass);
395  unsigned AndReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
396  BuildMI(BB, DL, TII.get(FConst), Tmp1)
397  .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, 0.0)));
398  BuildMI(BB, DL, TII.get(GE), SecondCmpReg).addReg(Tmp0).addReg(Tmp1);
399  BuildMI(BB, DL, TII.get(And), AndReg).addReg(CmpReg).addReg(SecondCmpReg);
400  CmpReg = AndReg;
401  }
402 
403  BuildMI(BB, DL, TII.get(Eqz), EqzReg).addReg(CmpReg);
404 
405  // Create the CFG diamond to select between doing the conversion or using
406  // the substitute value.
407  BuildMI(BB, DL, TII.get(WebAssembly::BR_IF)).addMBB(TrueMBB).addReg(EqzReg);
408  BuildMI(FalseMBB, DL, TII.get(LoweredOpcode), FalseReg).addReg(InReg);
409  BuildMI(FalseMBB, DL, TII.get(WebAssembly::BR)).addMBB(DoneMBB);
410  BuildMI(TrueMBB, DL, TII.get(IConst), TrueReg).addImm(Substitute);
411  BuildMI(*DoneMBB, DoneMBB->begin(), DL, TII.get(TargetOpcode::PHI), OutReg)
412  .addReg(FalseReg)
413  .addMBB(FalseMBB)
414  .addReg(TrueReg)
415  .addMBB(TrueMBB);
416 
417  return DoneMBB;
418 }
419 
420 MachineBasicBlock *WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
421  MachineInstr &MI, MachineBasicBlock *BB) const {
422  const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
423  DebugLoc DL = MI.getDebugLoc();
424 
425  switch (MI.getOpcode()) {
426  default:
427  llvm_unreachable("Unexpected instr type to insert");
428  case WebAssembly::FP_TO_SINT_I32_F32:
429  return LowerFPToInt(MI, DL, BB, TII, false, false, false,
430  WebAssembly::I32_TRUNC_S_F32);
431  case WebAssembly::FP_TO_UINT_I32_F32:
432  return LowerFPToInt(MI, DL, BB, TII, true, false, false,
433  WebAssembly::I32_TRUNC_U_F32);
434  case WebAssembly::FP_TO_SINT_I64_F32:
435  return LowerFPToInt(MI, DL, BB, TII, false, true, false,
436  WebAssembly::I64_TRUNC_S_F32);
437  case WebAssembly::FP_TO_UINT_I64_F32:
438  return LowerFPToInt(MI, DL, BB, TII, true, true, false,
439  WebAssembly::I64_TRUNC_U_F32);
440  case WebAssembly::FP_TO_SINT_I32_F64:
441  return LowerFPToInt(MI, DL, BB, TII, false, false, true,
442  WebAssembly::I32_TRUNC_S_F64);
443  case WebAssembly::FP_TO_UINT_I32_F64:
444  return LowerFPToInt(MI, DL, BB, TII, true, false, true,
445  WebAssembly::I32_TRUNC_U_F64);
446  case WebAssembly::FP_TO_SINT_I64_F64:
447  return LowerFPToInt(MI, DL, BB, TII, false, true, true,
448  WebAssembly::I64_TRUNC_S_F64);
449  case WebAssembly::FP_TO_UINT_I64_F64:
450  return LowerFPToInt(MI, DL, BB, TII, true, true, true,
451  WebAssembly::I64_TRUNC_U_F64);
452  llvm_unreachable("Unexpected instruction to emit with custom inserter");
453  }
454 }
455 
456 const char *
457 WebAssemblyTargetLowering::getTargetNodeName(unsigned Opcode) const {
458  switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) {
460  break;
461 #define HANDLE_NODETYPE(NODE) \
462  case WebAssemblyISD::NODE: \
463  return "WebAssemblyISD::" #NODE;
464 #include "WebAssemblyISD.def"
465 #undef HANDLE_NODETYPE
466  }
467  return nullptr;
468 }
469 
470 std::pair<unsigned, const TargetRegisterClass *>
471 WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
472  const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
473  // First, see if this is a constraint that directly corresponds to a
474  // WebAssembly register class.
475  if (Constraint.size() == 1) {
476  switch (Constraint[0]) {
477  case 'r':
478  assert(VT != MVT::iPTR && "Pointer MVT not expected here");
479  if (Subtarget->hasSIMD128() && VT.isVector()) {
480  if (VT.getSizeInBits() == 128)
481  return std::make_pair(0U, &WebAssembly::V128RegClass);
482  }
483  if (VT.isInteger() && !VT.isVector()) {
484  if (VT.getSizeInBits() <= 32)
485  return std::make_pair(0U, &WebAssembly::I32RegClass);
486  if (VT.getSizeInBits() <= 64)
487  return std::make_pair(0U, &WebAssembly::I64RegClass);
488  }
489  break;
490  default:
491  break;
492  }
493  }
494 
495  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
496 }
497 
498 bool WebAssemblyTargetLowering::isCheapToSpeculateCttz() const {
499  // Assume ctz is a relatively cheap operation.
500  return true;
501 }
502 
503 bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz() const {
504  // Assume clz is a relatively cheap operation.
505  return true;
506 }
507 
508 bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
509  const AddrMode &AM,
510  Type *Ty, unsigned AS,
511  Instruction *I) const {
512  // WebAssembly offsets are added as unsigned without wrapping. The
513  // isLegalAddressingMode gives us no way to determine if wrapping could be
514  // happening, so we approximate this by accepting only non-negative offsets.
515  if (AM.BaseOffs < 0)
516  return false;
517 
518  // WebAssembly has no scale register operands.
519  if (AM.Scale != 0)
520  return false;
521 
522  // Everything else is legal.
523  return true;
524 }
525 
526 bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses(
527  EVT /*VT*/, unsigned /*AddrSpace*/, unsigned /*Align*/, bool *Fast) const {
528  // WebAssembly supports unaligned accesses, though it should be declared
529  // with the p2align attribute on loads and stores which do so, and there
530  // may be a performance impact. We tell LLVM they're "fast" because
531  // for the kinds of things that LLVM uses this for (merging adjacent stores
532  // of constants, etc.), WebAssembly implementations will either want the
533  // unaligned access or they'll split anyway.
534  if (Fast)
535  *Fast = true;
536  return true;
537 }
538 
539 bool WebAssemblyTargetLowering::isIntDivCheap(EVT VT,
540  AttributeList Attr) const {
541  // The current thinking is that wasm engines will perform this optimization,
542  // so we can save on code size.
543  return true;
544 }
545 
546 EVT WebAssemblyTargetLowering::getSetCCResultType(const DataLayout &DL,
547  LLVMContext &C,
548  EVT VT) const {
549  if (VT.isVector())
551 
552  return TargetLowering::getSetCCResultType(DL, C, VT);
553 }
554 
555 bool WebAssemblyTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
556  const CallInst &I,
557  MachineFunction &MF,
558  unsigned Intrinsic) const {
559  switch (Intrinsic) {
560  case Intrinsic::wasm_atomic_notify:
562  Info.memVT = MVT::i32;
563  Info.ptrVal = I.getArgOperand(0);
564  Info.offset = 0;
565  Info.align = 4;
566  // atomic.notify instruction does not really load the memory specified with
567  // this argument, but MachineMemOperand should either be load or store, so
568  // we set this to a load.
569  // FIXME Volatile isn't really correct, but currently all LLVM atomic
570  // instructions are treated as volatiles in the backend, so we should be
571  // consistent. The same applies for wasm_atomic_wait intrinsics too.
573  return true;
574  case Intrinsic::wasm_atomic_wait_i32:
576  Info.memVT = MVT::i32;
577  Info.ptrVal = I.getArgOperand(0);
578  Info.offset = 0;
579  Info.align = 4;
581  return true;
582  case Intrinsic::wasm_atomic_wait_i64:
584  Info.memVT = MVT::i64;
585  Info.ptrVal = I.getArgOperand(0);
586  Info.offset = 0;
587  Info.align = 8;
589  return true;
590  default:
591  return false;
592  }
593 }
594 
595 //===----------------------------------------------------------------------===//
596 // WebAssembly Lowering private implementation.
597 //===----------------------------------------------------------------------===//
598 
599 //===----------------------------------------------------------------------===//
600 // Lowering Code
601 //===----------------------------------------------------------------------===//
602 
603 static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *Msg) {
605  DAG.getContext()->diagnose(
607 }
608 
609 // Test whether the given calling convention is supported.
610 static bool callingConvSupported(CallingConv::ID CallConv) {
611  // We currently support the language-independent target-independent
612  // conventions. We don't yet have a way to annotate calls with properties like
613  // "cold", and we don't have any call-clobbered registers, so these are mostly
614  // all handled the same.
615  return CallConv == CallingConv::C || CallConv == CallingConv::Fast ||
616  CallConv == CallingConv::Cold ||
617  CallConv == CallingConv::PreserveMost ||
618  CallConv == CallingConv::PreserveAll ||
619  CallConv == CallingConv::CXX_FAST_TLS;
620 }
621 
622 SDValue
623 WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
624  SmallVectorImpl<SDValue> &InVals) const {
625  SelectionDAG &DAG = CLI.DAG;
626  SDLoc DL = CLI.DL;
627  SDValue Chain = CLI.Chain;
628  SDValue Callee = CLI.Callee;
630  auto Layout = MF.getDataLayout();
631 
632  CallingConv::ID CallConv = CLI.CallConv;
633  if (!callingConvSupported(CallConv))
634  fail(DL, DAG,
635  "WebAssembly doesn't support language-specific or target-specific "
636  "calling conventions yet");
637  if (CLI.IsPatchPoint)
638  fail(DL, DAG, "WebAssembly doesn't support patch point yet");
639 
640  // WebAssembly doesn't currently support explicit tail calls. If they are
641  // required, fail. Otherwise, just disable them.
642  if ((CallConv == CallingConv::Fast && CLI.IsTailCall &&
644  (CLI.CS && CLI.CS.isMustTailCall()))
645  fail(DL, DAG, "WebAssembly doesn't support tail call yet");
646  CLI.IsTailCall = false;
647 
649  if (Ins.size() > 1)
650  fail(DL, DAG, "WebAssembly doesn't support more than 1 returned value yet");
651 
652  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
653  SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
654  unsigned NumFixedArgs = 0;
655  for (unsigned I = 0; I < Outs.size(); ++I) {
656  const ISD::OutputArg &Out = Outs[I];
657  SDValue &OutVal = OutVals[I];
658  if (Out.Flags.isNest())
659  fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
660  if (Out.Flags.isInAlloca())
661  fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
662  if (Out.Flags.isInConsecutiveRegs())
663  fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
664  if (Out.Flags.isInConsecutiveRegsLast())
665  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
666  if (Out.Flags.isByVal() && Out.Flags.getByValSize() != 0) {
667  auto &MFI = MF.getFrameInfo();
668  int FI = MFI.CreateStackObject(Out.Flags.getByValSize(),
669  Out.Flags.getByValAlign(),
670  /*isSS=*/false);
671  SDValue SizeNode =
672  DAG.getConstant(Out.Flags.getByValSize(), DL, MVT::i32);
673  SDValue FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
674  Chain = DAG.getMemcpy(
675  Chain, DL, FINode, OutVal, SizeNode, Out.Flags.getByValAlign(),
676  /*isVolatile*/ false, /*AlwaysInline=*/false,
677  /*isTailCall*/ false, MachinePointerInfo(), MachinePointerInfo());
678  OutVal = FINode;
679  }
680  // Count the number of fixed args *after* legalization.
681  NumFixedArgs += Out.IsFixed;
682  }
683 
684  bool IsVarArg = CLI.IsVarArg;
685  auto PtrVT = getPointerTy(Layout);
686 
687  // Analyze operands of the call, assigning locations to each operand.
689  CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
690 
691  if (IsVarArg) {
692  // Outgoing non-fixed arguments are placed in a buffer. First
693  // compute their offsets and the total amount of buffer space needed.
694  for (unsigned I = NumFixedArgs; I < Outs.size(); ++I) {
695  const ISD::OutputArg &Out = Outs[I];
696  SDValue &Arg = OutVals[I];
697  EVT VT = Arg.getValueType();
698  assert(VT != MVT::iPTR && "Legalized args should be concrete");
699  Type *Ty = VT.getTypeForEVT(*DAG.getContext());
700  unsigned Align = std::max(Out.Flags.getOrigAlign(),
701  Layout.getABITypeAlignment(Ty));
702  unsigned Offset = CCInfo.AllocateStack(Layout.getTypeAllocSize(Ty),
703  Align);
704  CCInfo.addLoc(CCValAssign::getMem(ArgLocs.size(), VT.getSimpleVT(),
705  Offset, VT.getSimpleVT(),
707  }
708  }
709 
710  unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
711 
712  SDValue FINode;
713  if (IsVarArg && NumBytes) {
714  // For non-fixed arguments, next emit stores to store the argument values
715  // to the stack buffer at the offsets computed above.
716  int FI = MF.getFrameInfo().CreateStackObject(NumBytes,
717  Layout.getStackAlignment(),
718  /*isSS=*/false);
719  unsigned ValNo = 0;
721  for (SDValue Arg :
722  make_range(OutVals.begin() + NumFixedArgs, OutVals.end())) {
723  assert(ArgLocs[ValNo].getValNo() == ValNo &&
724  "ArgLocs should remain in order and only hold varargs args");
725  unsigned Offset = ArgLocs[ValNo++].getLocMemOffset();
726  FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
727  SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, FINode,
728  DAG.getConstant(Offset, DL, PtrVT));
729  Chains.push_back(
730  DAG.getStore(Chain, DL, Arg, Add,
731  MachinePointerInfo::getFixedStack(MF, FI, Offset), 0));
732  }
733  if (!Chains.empty())
734  Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
735  } else if (IsVarArg) {
736  FINode = DAG.getIntPtrConstant(0, DL);
737  }
738 
739  if (Callee->getOpcode() == ISD::GlobalAddress) {
740  // If the callee is a GlobalAddress node (quite common, every direct call
741  // is) turn it into a TargetGlobalAddress node so that LowerGlobalAddress
742  // doesn't at MO_GOT which is not needed for direct calls.
743  GlobalAddressSDNode* GA = cast<GlobalAddressSDNode>(Callee);
744  Callee = DAG.getTargetGlobalAddress(GA->getGlobal(), DL,
746  GA->getOffset());
747  Callee = DAG.getNode(WebAssemblyISD::Wrapper, DL,
748  getPointerTy(DAG.getDataLayout()), Callee);
749  }
750 
751  // Compute the operands for the CALLn node.
753  Ops.push_back(Chain);
754  Ops.push_back(Callee);
755 
756  // Add all fixed arguments. Note that for non-varargs calls, NumFixedArgs
757  // isn't reliable.
758  Ops.append(OutVals.begin(),
759  IsVarArg ? OutVals.begin() + NumFixedArgs : OutVals.end());
760  // Add a pointer to the vararg buffer.
761  if (IsVarArg)
762  Ops.push_back(FINode);
763 
764  SmallVector<EVT, 8> InTys;
765  for (const auto &In : Ins) {
766  assert(!In.Flags.isByVal() && "byval is not valid for return values");
767  assert(!In.Flags.isNest() && "nest is not valid for return values");
768  if (In.Flags.isInAlloca())
769  fail(DL, DAG, "WebAssembly hasn't implemented inalloca return values");
770  if (In.Flags.isInConsecutiveRegs())
771  fail(DL, DAG, "WebAssembly hasn't implemented cons regs return values");
772  if (In.Flags.isInConsecutiveRegsLast())
773  fail(DL, DAG,
774  "WebAssembly hasn't implemented cons regs last return values");
775  // Ignore In.getOrigAlign() because all our arguments are passed in
776  // registers.
777  InTys.push_back(In.VT);
778  }
779  InTys.push_back(MVT::Other);
780  SDVTList InTyList = DAG.getVTList(InTys);
781  SDValue Res =
782  DAG.getNode(Ins.empty() ? WebAssemblyISD::CALL0 : WebAssemblyISD::CALL1,
783  DL, InTyList, Ops);
784  if (Ins.empty()) {
785  Chain = Res;
786  } else {
787  InVals.push_back(Res);
788  Chain = Res.getValue(1);
789  }
790 
791  return Chain;
792 }
793 
794 bool WebAssemblyTargetLowering::CanLowerReturn(
795  CallingConv::ID /*CallConv*/, MachineFunction & /*MF*/, bool /*IsVarArg*/,
797  LLVMContext & /*Context*/) const {
798  // WebAssembly can't currently handle returning tuples.
799  return Outs.size() <= 1;
800 }
801 
802 SDValue WebAssemblyTargetLowering::LowerReturn(
803  SDValue Chain, CallingConv::ID CallConv, bool /*IsVarArg*/,
805  const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
806  SelectionDAG &DAG) const {
807  assert(Outs.size() <= 1 && "WebAssembly can only return up to one value");
808  if (!callingConvSupported(CallConv))
809  fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
810 
811  SmallVector<SDValue, 4> RetOps(1, Chain);
812  RetOps.append(OutVals.begin(), OutVals.end());
813  Chain = DAG.getNode(WebAssemblyISD::RETURN, DL, MVT::Other, RetOps);
814 
815  // Record the number and types of the return values.
816  for (const ISD::OutputArg &Out : Outs) {
817  assert(!Out.Flags.isByVal() && "byval is not valid for return values");
818  assert(!Out.Flags.isNest() && "nest is not valid for return values");
819  assert(Out.IsFixed && "non-fixed return value is not valid");
820  if (Out.Flags.isInAlloca())
821  fail(DL, DAG, "WebAssembly hasn't implemented inalloca results");
822  if (Out.Flags.isInConsecutiveRegs())
823  fail(DL, DAG, "WebAssembly hasn't implemented cons regs results");
824  if (Out.Flags.isInConsecutiveRegsLast())
825  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last results");
826  }
827 
828  return Chain;
829 }
830 
831 SDValue WebAssemblyTargetLowering::LowerFormalArguments(
832  SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
833  const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
834  SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
835  if (!callingConvSupported(CallConv))
836  fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
837 
839  auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
840 
841  // Set up the incoming ARGUMENTS value, which serves to represent the liveness
842  // of the incoming values before they're represented by virtual registers.
843  MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
844 
845  for (const ISD::InputArg &In : Ins) {
846  if (In.Flags.isInAlloca())
847  fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
848  if (In.Flags.isNest())
849  fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
850  if (In.Flags.isInConsecutiveRegs())
851  fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
852  if (In.Flags.isInConsecutiveRegsLast())
853  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
854  // Ignore In.getOrigAlign() because all our arguments are passed in
855  // registers.
856  InVals.push_back(In.Used ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
857  DAG.getTargetConstant(InVals.size(),
858  DL, MVT::i32))
859  : DAG.getUNDEF(In.VT));
860 
861  // Record the number and types of arguments.
862  MFI->addParam(In.VT);
863  }
864 
865  // Varargs are copied into a buffer allocated by the caller, and a pointer to
866  // the buffer is passed as an argument.
867  if (IsVarArg) {
868  MVT PtrVT = getPointerTy(MF.getDataLayout());
869  unsigned VarargVreg =
871  MFI->setVarargBufferVreg(VarargVreg);
872  Chain = DAG.getCopyToReg(
873  Chain, DL, VarargVreg,
874  DAG.getNode(WebAssemblyISD::ARGUMENT, DL, PtrVT,
875  DAG.getTargetConstant(Ins.size(), DL, MVT::i32)));
876  MFI->addParam(PtrVT);
877  }
878 
879  // Record the number and types of arguments and results.
880  SmallVector<MVT, 4> Params;
883  DAG.getTarget(), Params, Results);
884  for (MVT VT : Results)
885  MFI->addResult(VT);
886  // TODO: Use signatures in WebAssemblyMachineFunctionInfo too and unify
887  // the param logic here with ComputeSignatureVTs
888  assert(MFI->getParams().size() == Params.size() &&
889  std::equal(MFI->getParams().begin(), MFI->getParams().end(),
890  Params.begin()));
891 
892  return Chain;
893 }
894 
895 //===----------------------------------------------------------------------===//
896 // Custom lowering hooks.
897 //===----------------------------------------------------------------------===//
898 
899 SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
900  SelectionDAG &DAG) const {
901  SDLoc DL(Op);
902  switch (Op.getOpcode()) {
903  default:
904  llvm_unreachable("unimplemented operation lowering");
905  return SDValue();
906  case ISD::FrameIndex:
907  return LowerFrameIndex(Op, DAG);
908  case ISD::GlobalAddress:
909  return LowerGlobalAddress(Op, DAG);
910  case ISD::ExternalSymbol:
911  return LowerExternalSymbol(Op, DAG);
912  case ISD::JumpTable:
913  return LowerJumpTable(Op, DAG);
914  case ISD::BR_JT:
915  return LowerBR_JT(Op, DAG);
916  case ISD::VASTART:
917  return LowerVASTART(Op, DAG);
918  case ISD::BlockAddress:
919  case ISD::BRIND:
920  fail(DL, DAG, "WebAssembly hasn't implemented computed gotos");
921  return SDValue();
922  case ISD::RETURNADDR: // Probably nothing meaningful can be returned here.
923  fail(DL, DAG, "WebAssembly hasn't implemented __builtin_return_address");
924  return SDValue();
925  case ISD::FRAMEADDR:
926  return LowerFRAMEADDR(Op, DAG);
927  case ISD::CopyToReg:
928  return LowerCopyToReg(Op, DAG);
931  return LowerAccessVectorElement(Op, DAG);
932  case ISD::INTRINSIC_VOID:
935  return LowerIntrinsic(Op, DAG);
937  return LowerSIGN_EXTEND_INREG(Op, DAG);
938  case ISD::BUILD_VECTOR:
939  return LowerBUILD_VECTOR(Op, DAG);
940  case ISD::VECTOR_SHUFFLE:
941  return LowerVECTOR_SHUFFLE(Op, DAG);
942  case ISD::SHL:
943  case ISD::SRA:
944  case ISD::SRL:
945  return LowerShift(Op, DAG);
946  }
947 }
948 
949 SDValue WebAssemblyTargetLowering::LowerCopyToReg(SDValue Op,
950  SelectionDAG &DAG) const {
951  SDValue Src = Op.getOperand(2);
952  if (isa<FrameIndexSDNode>(Src.getNode())) {
953  // CopyToReg nodes don't support FrameIndex operands. Other targets select
954  // the FI to some LEA-like instruction, but since we don't have that, we
955  // need to insert some kind of instruction that can take an FI operand and
956  // produces a value usable by CopyToReg (i.e. in a vreg). So insert a dummy
957  // local.copy between Op and its FI operand.
958  SDValue Chain = Op.getOperand(0);
959  SDLoc DL(Op);
960  unsigned Reg = cast<RegisterSDNode>(Op.getOperand(1))->getReg();
961  EVT VT = Src.getValueType();
962  SDValue Copy(DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32
963  : WebAssembly::COPY_I64,
964  DL, VT, Src),
965  0);
966  return Op.getNode()->getNumValues() == 1
967  ? DAG.getCopyToReg(Chain, DL, Reg, Copy)
968  : DAG.getCopyToReg(Chain, DL, Reg, Copy,
969  Op.getNumOperands() == 4 ? Op.getOperand(3)
970  : SDValue());
971  }
972  return SDValue();
973 }
974 
975 SDValue WebAssemblyTargetLowering::LowerFrameIndex(SDValue Op,
976  SelectionDAG &DAG) const {
977  int FI = cast<FrameIndexSDNode>(Op)->getIndex();
978  return DAG.getTargetFrameIndex(FI, Op.getValueType());
979 }
980 
981 SDValue WebAssemblyTargetLowering::LowerFRAMEADDR(SDValue Op,
982  SelectionDAG &DAG) const {
983  // Non-zero depths are not supported by WebAssembly currently. Use the
984  // legalizer's default expansion, which is to return 0 (what this function is
985  // documented to do).
986  if (Op.getConstantOperandVal(0) > 0)
987  return SDValue();
988 
990  EVT VT = Op.getValueType();
991  unsigned FP =
993  return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), FP, VT);
994 }
995 
996 SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
997  SelectionDAG &DAG) const {
998  SDLoc DL(Op);
999  const auto *GA = cast<GlobalAddressSDNode>(Op);
1000  EVT VT = Op.getValueType();
1001  assert(GA->getTargetFlags() == 0 &&
1002  "Unexpected target flags on generic GlobalAddressSDNode");
1003  if (GA->getAddressSpace() != 0)
1004  fail(DL, DAG, "WebAssembly only expects the 0 address space");
1005 
1006  unsigned OperandFlags = 0;
1007  if (isPositionIndependent()) {
1008  const GlobalValue *GV = GA->getGlobal();
1009  if (getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV)) {
1010  MachineFunction &MF = DAG.getMachineFunction();
1011  MVT PtrVT = getPointerTy(MF.getDataLayout());
1012  const char *BaseName;
1013  if (GV->getValueType()->isFunctionTy()) {
1014  BaseName = MF.createExternalSymbolName("__table_base");
1015  OperandFlags = WebAssemblyII::MO_TABLE_BASE_REL;
1016  }
1017  else {
1018  BaseName = MF.createExternalSymbolName("__memory_base");
1019  OperandFlags = WebAssemblyII::MO_MEMORY_BASE_REL;
1020  }
1021  SDValue BaseAddr =
1022  DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT,
1023  DAG.getTargetExternalSymbol(BaseName, PtrVT));
1024 
1025  SDValue SymAddr = DAG.getNode(
1027  DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset(),
1028  OperandFlags));
1029 
1030  return DAG.getNode(ISD::ADD, DL, VT, BaseAddr, SymAddr);
1031  } else {
1032  OperandFlags = WebAssemblyII::MO_GOT;
1033  }
1034  }
1035 
1036  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1037  DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT,
1038  GA->getOffset(), OperandFlags));
1039 }
1040 
1041 SDValue
1042 WebAssemblyTargetLowering::LowerExternalSymbol(SDValue Op,
1043  SelectionDAG &DAG) const {
1044  SDLoc DL(Op);
1045  const auto *ES = cast<ExternalSymbolSDNode>(Op);
1046  EVT VT = Op.getValueType();
1047  assert(ES->getTargetFlags() == 0 &&
1048  "Unexpected target flags on generic ExternalSymbolSDNode");
1049  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1050  DAG.getTargetExternalSymbol(ES->getSymbol(), VT));
1051 }
1052 
1053 SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op,
1054  SelectionDAG &DAG) const {
1055  // There's no need for a Wrapper node because we always incorporate a jump
1056  // table operand into a BR_TABLE instruction, rather than ever
1057  // materializing it in a register.
1058  const JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
1059  return DAG.getTargetJumpTable(JT->getIndex(), Op.getValueType(),
1060  JT->getTargetFlags());
1061 }
1062 
1063 SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op,
1064  SelectionDAG &DAG) const {
1065  SDLoc DL(Op);
1066  SDValue Chain = Op.getOperand(0);
1067  const auto *JT = cast<JumpTableSDNode>(Op.getOperand(1));
1068  SDValue Index = Op.getOperand(2);
1069  assert(JT->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");
1070 
1072  Ops.push_back(Chain);
1073  Ops.push_back(Index);
1074 
1076  const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs;
1077 
1078  // Add an operand for each case.
1079  for (auto MBB : MBBs)
1080  Ops.push_back(DAG.getBasicBlock(MBB));
1081 
1082  // TODO: For now, we just pick something arbitrary for a default case for now.
1083  // We really want to sniff out the guard and put in the real default case (and
1084  // delete the guard).
1085  Ops.push_back(DAG.getBasicBlock(MBBs[0]));
1086 
1087  return DAG.getNode(WebAssemblyISD::BR_TABLE, DL, MVT::Other, Ops);
1088 }
1089 
1090 SDValue WebAssemblyTargetLowering::LowerVASTART(SDValue Op,
1091  SelectionDAG &DAG) const {
1092  SDLoc DL(Op);
1094 
1095  auto *MFI = DAG.getMachineFunction().getInfo<WebAssemblyFunctionInfo>();
1096  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
1097 
1098  SDValue ArgN = DAG.getCopyFromReg(DAG.getEntryNode(), DL,
1099  MFI->getVarargBufferVreg(), PtrVT);
1100  return DAG.getStore(Op.getOperand(0), DL, ArgN, Op.getOperand(1),
1101  MachinePointerInfo(SV), 0);
1102 }
1103 
1104 SDValue WebAssemblyTargetLowering::LowerIntrinsic(SDValue Op,
1105  SelectionDAG &DAG) const {
1106  MachineFunction &MF = DAG.getMachineFunction();
1107  unsigned IntNo;
1108  switch (Op.getOpcode()) {
1109  case ISD::INTRINSIC_VOID:
1111  IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
1112  break;
1114  IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
1115  break;
1116  default:
1117  llvm_unreachable("Invalid intrinsic");
1118  }
1119  SDLoc DL(Op);
1120 
1121  switch (IntNo) {
1122  default:
1123  return SDValue(); // Don't custom lower most intrinsics.
1124 
1125  case Intrinsic::wasm_lsda: {
1126  EVT VT = Op.getValueType();
1127  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1128  MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
1129  auto &Context = MF.getMMI().getContext();
1130  MCSymbol *S = Context.getOrCreateSymbol(Twine("GCC_except_table") +
1131  Twine(MF.getFunctionNumber()));
1132  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1133  DAG.getMCSymbol(S, PtrVT));
1134  }
1135 
1136  case Intrinsic::wasm_throw: {
1137  // We only support C++ exceptions for now
1138  int Tag = cast<ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue();
1139  if (Tag != CPP_EXCEPTION)
1140  llvm_unreachable("Invalid tag!");
1141  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1142  MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
1143  const char *SymName = MF.createExternalSymbolName("__cpp_exception");
1144  SDValue SymNode = DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT,
1145  DAG.getTargetExternalSymbol(SymName, PtrVT));
1146  return DAG.getNode(WebAssemblyISD::THROW, DL,
1147  MVT::Other, // outchain type
1148  {
1149  Op.getOperand(0), // inchain
1150  SymNode, // exception symbol
1151  Op.getOperand(3) // thrown value
1152  });
1153  }
1154  }
1155 }
1156 
1157 SDValue
1158 WebAssemblyTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
1159  SelectionDAG &DAG) const {
1160  // If sign extension operations are disabled, allow sext_inreg only if operand
1161  // is a vector extract. SIMD does not depend on sign extension operations, but
1162  // allowing sext_inreg in this context lets us have simple patterns to select
1163  // extract_lane_s instructions. Expanding sext_inreg everywhere would be
1164  // simpler in this file, but would necessitate large and brittle patterns to
1165  // undo the expansion and select extract_lane_s instructions.
1166  assert(!Subtarget->hasSignExt() && Subtarget->hasSIMD128());
1168  return Op;
1169  // Otherwise expand
1170  return SDValue();
1171 }
1172 
1173 SDValue WebAssemblyTargetLowering::LowerBUILD_VECTOR(SDValue Op,
1174  SelectionDAG &DAG) const {
1175  SDLoc DL(Op);
1176  const EVT VecT = Op.getValueType();
1177  const EVT LaneT = Op.getOperand(0).getValueType();
1178  const size_t Lanes = Op.getNumOperands();
1179  auto IsConstant = [](const SDValue &V) {
1180  return V.getOpcode() == ISD::Constant || V.getOpcode() == ISD::ConstantFP;
1181  };
1182 
1183  // Find the most common operand, which is approximately the best to splat
1184  using Entry = std::pair<SDValue, size_t>;
1185  SmallVector<Entry, 16> ValueCounts;
1186  size_t NumConst = 0, NumDynamic = 0;
1187  for (const SDValue &Lane : Op->op_values()) {
1188  if (Lane.isUndef()) {
1189  continue;
1190  } else if (IsConstant(Lane)) {
1191  NumConst++;
1192  } else {
1193  NumDynamic++;
1194  }
1195  auto CountIt = std::find_if(ValueCounts.begin(), ValueCounts.end(),
1196  [&Lane](Entry A) { return A.first == Lane; });
1197  if (CountIt == ValueCounts.end()) {
1198  ValueCounts.emplace_back(Lane, 1);
1199  } else {
1200  CountIt->second++;
1201  }
1202  }
1203  auto CommonIt =
1204  std::max_element(ValueCounts.begin(), ValueCounts.end(),
1205  [](Entry A, Entry B) { return A.second < B.second; });
1206  assert(CommonIt != ValueCounts.end() && "Unexpected all-undef build_vector");
1207  SDValue SplatValue = CommonIt->first;
1208  size_t NumCommon = CommonIt->second;
1209 
1210  // If v128.const is available, consider using it instead of a splat
1211  if (Subtarget->hasUnimplementedSIMD128()) {
1212  // {i32,i64,f32,f64}.const opcode, and value
1213  const size_t ConstBytes = 1 + std::max(size_t(4), 16 / Lanes);
1214  // SIMD prefix and opcode
1215  const size_t SplatBytes = 2;
1216  const size_t SplatConstBytes = SplatBytes + ConstBytes;
1217  // SIMD prefix, opcode, and lane index
1218  const size_t ReplaceBytes = 3;
1219  const size_t ReplaceConstBytes = ReplaceBytes + ConstBytes;
1220  // SIMD prefix, v128.const opcode, and 128-bit value
1221  const size_t VecConstBytes = 18;
1222  // Initial v128.const and a replace_lane for each non-const operand
1223  const size_t ConstInitBytes = VecConstBytes + NumDynamic * ReplaceBytes;
1224  // Initial splat and all necessary replace_lanes
1225  const size_t SplatInitBytes =
1226  IsConstant(SplatValue)
1227  // Initial constant splat
1228  ? (SplatConstBytes +
1229  // Constant replace_lanes
1230  (NumConst - NumCommon) * ReplaceConstBytes +
1231  // Dynamic replace_lanes
1232  (NumDynamic * ReplaceBytes))
1233  // Initial dynamic splat
1234  : (SplatBytes +
1235  // Constant replace_lanes
1236  (NumConst * ReplaceConstBytes) +
1237  // Dynamic replace_lanes
1238  (NumDynamic - NumCommon) * ReplaceBytes);
1239  if (ConstInitBytes < SplatInitBytes) {
1240  // Create build_vector that will lower to initial v128.const
1241  SmallVector<SDValue, 16> ConstLanes;
1242  for (const SDValue &Lane : Op->op_values()) {
1243  if (IsConstant(Lane)) {
1244  ConstLanes.push_back(Lane);
1245  } else if (LaneT.isFloatingPoint()) {
1246  ConstLanes.push_back(DAG.getConstantFP(0, DL, LaneT));
1247  } else {
1248  ConstLanes.push_back(DAG.getConstant(0, DL, LaneT));
1249  }
1250  }
1251  SDValue Result = DAG.getBuildVector(VecT, DL, ConstLanes);
1252  // Add replace_lane instructions for non-const lanes
1253  for (size_t I = 0; I < Lanes; ++I) {
1254  const SDValue &Lane = Op->getOperand(I);
1255  if (!Lane.isUndef() && !IsConstant(Lane))
1256  Result = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VecT, Result, Lane,
1257  DAG.getConstant(I, DL, MVT::i32));
1258  }
1259  return Result;
1260  }
1261  }
1262  // Use a splat for the initial vector
1263  SDValue Result = DAG.getSplatBuildVector(VecT, DL, SplatValue);
1264  // Add replace_lane instructions for other values
1265  for (size_t I = 0; I < Lanes; ++I) {
1266  const SDValue &Lane = Op->getOperand(I);
1267  if (Lane != SplatValue)
1268  Result = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VecT, Result, Lane,
1269  DAG.getConstant(I, DL, MVT::i32));
1270  }
1271  return Result;
1272 }
1273 
1274 SDValue
1275 WebAssemblyTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
1276  SelectionDAG &DAG) const {
1277  SDLoc DL(Op);
1278  ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(Op.getNode())->getMask();
1280  assert(VecType.is128BitVector() && "Unexpected shuffle vector type");
1281  size_t LaneBytes = VecType.getVectorElementType().getSizeInBits() / 8;
1282 
1283  // Space for two vector args and sixteen mask indices
1284  SDValue Ops[18];
1285  size_t OpIdx = 0;
1286  Ops[OpIdx++] = Op.getOperand(0);
1287  Ops[OpIdx++] = Op.getOperand(1);
1288 
1289  // Expand mask indices to byte indices and materialize them as operands
1290  for (int M : Mask) {
1291  for (size_t J = 0; J < LaneBytes; ++J) {
1292  // Lower undefs (represented by -1 in mask) to zero
1293  uint64_t ByteIndex = M == -1 ? 0 : (uint64_t)M * LaneBytes + J;
1294  Ops[OpIdx++] = DAG.getConstant(ByteIndex, DL, MVT::i32);
1295  }
1296  }
1297 
1298  return DAG.getNode(WebAssemblyISD::SHUFFLE, DL, Op.getValueType(), Ops);
1299 }
1300 
1301 SDValue
1302 WebAssemblyTargetLowering::LowerAccessVectorElement(SDValue Op,
1303  SelectionDAG &DAG) const {
1304  // Allow constant lane indices, expand variable lane indices
1305  SDNode *IdxNode = Op.getOperand(Op.getNumOperands() - 1).getNode();
1306  if (isa<ConstantSDNode>(IdxNode) || IdxNode->isUndef())
1307  return Op;
1308  else
1309  // Perform default expansion
1310  return SDValue();
1311 }
1312 
1315  // 32-bit and 64-bit unrolled shifts will have proper semantics
1316  if (LaneT.bitsGE(MVT::i32))
1317  return DAG.UnrollVectorOp(Op.getNode());
1318  // Otherwise mask the shift value to get proper semantics from 32-bit shift
1319  SDLoc DL(Op);
1320  SDValue ShiftVal = Op.getOperand(1);
1321  uint64_t MaskVal = LaneT.getSizeInBits() - 1;
1322  SDValue MaskedShiftVal = DAG.getNode(
1323  ISD::AND, // mask opcode
1324  DL, ShiftVal.getValueType(), // masked value type
1325  ShiftVal, // original shift value operand
1326  DAG.getConstant(MaskVal, DL, ShiftVal.getValueType()) // mask operand
1327  );
1328 
1329  return DAG.UnrollVectorOp(
1330  DAG.getNode(Op.getOpcode(), // original shift opcode
1331  DL, Op.getValueType(), // original return type
1332  Op.getOperand(0), // original vector operand,
1333  MaskedShiftVal // new masked shift value operand
1334  )
1335  .getNode());
1336 }
1337 
1338 SDValue WebAssemblyTargetLowering::LowerShift(SDValue Op,
1339  SelectionDAG &DAG) const {
1340  SDLoc DL(Op);
1341 
1342  // Only manually lower vector shifts
1344 
1345  // Expand all vector shifts until V8 fixes its implementation
1346  // TODO: remove this once V8 is fixed
1347  if (!Subtarget->hasUnimplementedSIMD128())
1348  return unrollVectorShift(Op, DAG);
1349 
1350  // Unroll non-splat vector shifts
1351  BuildVectorSDNode *ShiftVec;
1352  SDValue SplatVal;
1353  if (!(ShiftVec = dyn_cast<BuildVectorSDNode>(Op.getOperand(1).getNode())) ||
1354  !(SplatVal = ShiftVec->getSplatValue()))
1355  return unrollVectorShift(Op, DAG);
1356 
1357  // All splats except i64x2 const splats are handled by patterns
1358  auto *SplatConst = dyn_cast<ConstantSDNode>(SplatVal);
1359  if (!SplatConst || Op.getSimpleValueType() != MVT::v2i64)
1360  return Op;
1361 
1362  // i64x2 const splats are custom lowered to avoid unnecessary wraps
1363  unsigned Opcode;
1364  switch (Op.getOpcode()) {
1365  case ISD::SHL:
1366  Opcode = WebAssemblyISD::VEC_SHL;
1367  break;
1368  case ISD::SRA:
1369  Opcode = WebAssemblyISD::VEC_SHR_S;
1370  break;
1371  case ISD::SRL:
1372  Opcode = WebAssemblyISD::VEC_SHR_U;
1373  break;
1374  default:
1375  llvm_unreachable("unexpected opcode");
1376  }
1377  APInt Shift = SplatConst->getAPIntValue().zextOrTrunc(32);
1378  return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(0),
1379  DAG.getConstant(Shift, DL, MVT::i32));
1380 }
1381 
1382 //===----------------------------------------------------------------------===//
1383 // WebAssembly Optimization Hooks
1384 //===----------------------------------------------------------------------===//
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...
void setMinimumJumpTableEntries(unsigned Val)
Indicate the minimum number of blocks to generate jump tables.
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:673
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...
C - The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0...
Definition: ISDOpcodes.h:628
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition: ISDOpcodes.h:386
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:725
This class represents a function call, abstracting a target machine&#39;s calling convention.
unsigned Reg
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.
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:454
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:1218
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:475
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:429
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:721
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:448
const MCContext & getContext() const
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:200
Fast - This calling convention attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:42
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:867
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:346
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:652
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
unsigned const MachineRegisterInfo * MRI
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:754
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:351
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:793
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:745
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:196
virtual 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...
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:358
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:432
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
Definition: ISDOpcodes.h:600
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
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:439
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition: ISDOpcodes.h:331
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:661
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:750
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:406
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:505
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.
void setLibcallName(RTLIB::Libcall Call, const char *Name)
Rename the default libcall routine name for the specified libcall.
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:631
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:321
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:399
BRIND - Indirect branch.
Definition: ISDOpcodes.h:657
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary...
Definition: ISDOpcodes.h:646