LLVM  10.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
188  if (Subtarget->hasUnimplementedSIMD128())
190  }
191 
192  // Expand additional SIMD ops that V8 hasn't implemented yet
193  if (!Subtarget->hasUnimplementedSIMD128()) {
196  }
197  }
198 
199  // As a special case, these operators use the type to mean the type to
200  // sign-extend from.
202  if (!Subtarget->hasSignExt()) {
203  // Sign extends are legal only when extending a vector extract
204  auto Action = Subtarget->hasSIMD128() ? Custom : Expand;
205  for (auto T : {MVT::i8, MVT::i16, MVT::i32})
207  }
210 
211  // Dynamic stack allocation: use the default expansion.
215 
218 
219  // Expand these forms; we pattern-match the forms that we can handle in isel.
220  for (auto T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
221  for (auto Op : {ISD::BR_CC, ISD::SELECT_CC})
223 
224  // We have custom switch handling.
226 
227  // WebAssembly doesn't have:
228  // - Floating-point extending loads.
229  // - Floating-point truncating stores.
230  // - i1 extending loads.
231  // - truncating SIMD stores and most extending loads
234  for (auto T : MVT::integer_valuetypes())
237  if (Subtarget->hasSIMD128()) {
239  MVT::v2f64}) {
240  for (auto MemT : MVT::fixedlen_vector_valuetypes()) {
241  if (MVT(T) != MemT) {
242  setTruncStoreAction(T, MemT, Expand);
244  setLoadExtAction(Ext, T, MemT, Expand);
245  }
246  }
247  }
248  // But some vector extending loads are legal
249  if (Subtarget->hasUnimplementedSIMD128()) {
250  for (auto Ext : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}) {
254  }
255  }
256  }
257 
258  // Don't do anything clever with build_pairs
260 
261  // Trap lowers to wasm unreachable
263 
264  // Exception handling intrinsics
267 
269 
270  // Override the __gnu_f2h_ieee/__gnu_h2f_ieee names so that the f32 name is
271  // consistent with the f64 and f128 names.
272  setLibcallName(RTLIB::FPEXT_F16_F32, "__extendhfsf2");
273  setLibcallName(RTLIB::FPROUND_F32_F16, "__truncsfhf2");
274 
275  // Define the emscripten name for return address helper.
276  // TODO: when implementing other WASM backends, make this generic or only do
277  // this on emscripten depending on what they end up doing.
278  setLibcallName(RTLIB::RETURN_ADDRESS, "emscripten_return_address");
279 
280  // Always convert switches to br_tables unless there is only one case, which
281  // is equivalent to a simple branch. This reduces code size for wasm, and we
282  // defer possible jump table optimizations to the VM.
284 }
285 
287 WebAssemblyTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
288  // We have wasm instructions for these
289  switch (AI->getOperation()) {
290  case AtomicRMWInst::Add:
291  case AtomicRMWInst::Sub:
292  case AtomicRMWInst::And:
293  case AtomicRMWInst::Or:
294  case AtomicRMWInst::Xor:
295  case AtomicRMWInst::Xchg:
297  default:
298  break;
299  }
301 }
302 
303 FastISel *WebAssemblyTargetLowering::createFastISel(
304  FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo) const {
305  return WebAssembly::createFastISel(FuncInfo, LibInfo);
306 }
307 
308 MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
309  EVT VT) const {
310  unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1);
311  if (BitWidth > 1 && BitWidth < 8)
312  BitWidth = 8;
313 
314  if (BitWidth > 64) {
315  // The shift will be lowered to a libcall, and compiler-rt libcalls expect
316  // the count to be an i32.
317  BitWidth = 32;
318  assert(BitWidth >= Log2_32_Ceil(VT.getSizeInBits()) &&
319  "32-bit shift counts ought to be enough for anyone");
320  }
321 
322  MVT Result = MVT::getIntegerVT(BitWidth);
324  "Unable to represent scalar shift amount type");
325  return Result;
326 }
327 
328 // Lower an fp-to-int conversion operator from the LLVM opcode, which has an
329 // undefined result on invalid/overflow, to the WebAssembly opcode, which
330 // traps on invalid/overflow.
332  MachineBasicBlock *BB,
333  const TargetInstrInfo &TII,
334  bool IsUnsigned, bool Int64,
335  bool Float64, unsigned LoweredOpcode) {
337 
338  Register OutReg = MI.getOperand(0).getReg();
339  Register InReg = MI.getOperand(1).getReg();
340 
341  unsigned Abs = Float64 ? WebAssembly::ABS_F64 : WebAssembly::ABS_F32;
342  unsigned FConst = Float64 ? WebAssembly::CONST_F64 : WebAssembly::CONST_F32;
343  unsigned LT = Float64 ? WebAssembly::LT_F64 : WebAssembly::LT_F32;
344  unsigned GE = Float64 ? WebAssembly::GE_F64 : WebAssembly::GE_F32;
345  unsigned IConst = Int64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32;
346  unsigned Eqz = WebAssembly::EQZ_I32;
347  unsigned And = WebAssembly::AND_I32;
348  int64_t Limit = Int64 ? INT64_MIN : INT32_MIN;
349  int64_t Substitute = IsUnsigned ? 0 : Limit;
350  double CmpVal = IsUnsigned ? -(double)Limit * 2.0 : -(double)Limit;
351  auto &Context = BB->getParent()->getFunction().getContext();
353 
354  const BasicBlock *LLVMBB = BB->getBasicBlock();
355  MachineFunction *F = BB->getParent();
356  MachineBasicBlock *TrueMBB = F->CreateMachineBasicBlock(LLVMBB);
357  MachineBasicBlock *FalseMBB = F->CreateMachineBasicBlock(LLVMBB);
358  MachineBasicBlock *DoneMBB = F->CreateMachineBasicBlock(LLVMBB);
359 
361  F->insert(It, FalseMBB);
362  F->insert(It, TrueMBB);
363  F->insert(It, DoneMBB);
364 
365  // Transfer the remainder of BB and its successor edges to DoneMBB.
366  DoneMBB->splice(DoneMBB->begin(), BB, std::next(MI.getIterator()), BB->end());
367  DoneMBB->transferSuccessorsAndUpdatePHIs(BB);
368 
369  BB->addSuccessor(TrueMBB);
370  BB->addSuccessor(FalseMBB);
371  TrueMBB->addSuccessor(DoneMBB);
372  FalseMBB->addSuccessor(DoneMBB);
373 
374  unsigned Tmp0, Tmp1, CmpReg, EqzReg, FalseReg, TrueReg;
375  Tmp0 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
376  Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
377  CmpReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
378  EqzReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
379  FalseReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
380  TrueReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
381 
382  MI.eraseFromParent();
383  // For signed numbers, we can do a single comparison to determine whether
384  // fabs(x) is within range.
385  if (IsUnsigned) {
386  Tmp0 = InReg;
387  } else {
388  BuildMI(BB, DL, TII.get(Abs), Tmp0).addReg(InReg);
389  }
390  BuildMI(BB, DL, TII.get(FConst), Tmp1)
391  .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, CmpVal)));
392  BuildMI(BB, DL, TII.get(LT), CmpReg).addReg(Tmp0).addReg(Tmp1);
393 
394  // For unsigned numbers, we have to do a separate comparison with zero.
395  if (IsUnsigned) {
396  Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
397  Register SecondCmpReg =
398  MRI.createVirtualRegister(&WebAssembly::I32RegClass);
399  Register AndReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
400  BuildMI(BB, DL, TII.get(FConst), Tmp1)
401  .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, 0.0)));
402  BuildMI(BB, DL, TII.get(GE), SecondCmpReg).addReg(Tmp0).addReg(Tmp1);
403  BuildMI(BB, DL, TII.get(And), AndReg).addReg(CmpReg).addReg(SecondCmpReg);
404  CmpReg = AndReg;
405  }
406 
407  BuildMI(BB, DL, TII.get(Eqz), EqzReg).addReg(CmpReg);
408 
409  // Create the CFG diamond to select between doing the conversion or using
410  // the substitute value.
411  BuildMI(BB, DL, TII.get(WebAssembly::BR_IF)).addMBB(TrueMBB).addReg(EqzReg);
412  BuildMI(FalseMBB, DL, TII.get(LoweredOpcode), FalseReg).addReg(InReg);
413  BuildMI(FalseMBB, DL, TII.get(WebAssembly::BR)).addMBB(DoneMBB);
414  BuildMI(TrueMBB, DL, TII.get(IConst), TrueReg).addImm(Substitute);
415  BuildMI(*DoneMBB, DoneMBB->begin(), DL, TII.get(TargetOpcode::PHI), OutReg)
416  .addReg(FalseReg)
417  .addMBB(FalseMBB)
418  .addReg(TrueReg)
419  .addMBB(TrueMBB);
420 
421  return DoneMBB;
422 }
423 
424 MachineBasicBlock *WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
425  MachineInstr &MI, MachineBasicBlock *BB) const {
426  const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
427  DebugLoc DL = MI.getDebugLoc();
428 
429  switch (MI.getOpcode()) {
430  default:
431  llvm_unreachable("Unexpected instr type to insert");
432  case WebAssembly::FP_TO_SINT_I32_F32:
433  return LowerFPToInt(MI, DL, BB, TII, false, false, false,
434  WebAssembly::I32_TRUNC_S_F32);
435  case WebAssembly::FP_TO_UINT_I32_F32:
436  return LowerFPToInt(MI, DL, BB, TII, true, false, false,
437  WebAssembly::I32_TRUNC_U_F32);
438  case WebAssembly::FP_TO_SINT_I64_F32:
439  return LowerFPToInt(MI, DL, BB, TII, false, true, false,
440  WebAssembly::I64_TRUNC_S_F32);
441  case WebAssembly::FP_TO_UINT_I64_F32:
442  return LowerFPToInt(MI, DL, BB, TII, true, true, false,
443  WebAssembly::I64_TRUNC_U_F32);
444  case WebAssembly::FP_TO_SINT_I32_F64:
445  return LowerFPToInt(MI, DL, BB, TII, false, false, true,
446  WebAssembly::I32_TRUNC_S_F64);
447  case WebAssembly::FP_TO_UINT_I32_F64:
448  return LowerFPToInt(MI, DL, BB, TII, true, false, true,
449  WebAssembly::I32_TRUNC_U_F64);
450  case WebAssembly::FP_TO_SINT_I64_F64:
451  return LowerFPToInt(MI, DL, BB, TII, false, true, true,
452  WebAssembly::I64_TRUNC_S_F64);
453  case WebAssembly::FP_TO_UINT_I64_F64:
454  return LowerFPToInt(MI, DL, BB, TII, true, true, true,
455  WebAssembly::I64_TRUNC_U_F64);
456  llvm_unreachable("Unexpected instruction to emit with custom inserter");
457  }
458 }
459 
460 const char *
461 WebAssemblyTargetLowering::getTargetNodeName(unsigned Opcode) const {
462  switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) {
464  break;
465 #define HANDLE_NODETYPE(NODE) \
466  case WebAssemblyISD::NODE: \
467  return "WebAssemblyISD::" #NODE;
468 #include "WebAssemblyISD.def"
469 #undef HANDLE_NODETYPE
470  }
471  return nullptr;
472 }
473 
474 std::pair<unsigned, const TargetRegisterClass *>
475 WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
476  const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
477  // First, see if this is a constraint that directly corresponds to a
478  // WebAssembly register class.
479  if (Constraint.size() == 1) {
480  switch (Constraint[0]) {
481  case 'r':
482  assert(VT != MVT::iPTR && "Pointer MVT not expected here");
483  if (Subtarget->hasSIMD128() && VT.isVector()) {
484  if (VT.getSizeInBits() == 128)
485  return std::make_pair(0U, &WebAssembly::V128RegClass);
486  }
487  if (VT.isInteger() && !VT.isVector()) {
488  if (VT.getSizeInBits() <= 32)
489  return std::make_pair(0U, &WebAssembly::I32RegClass);
490  if (VT.getSizeInBits() <= 64)
491  return std::make_pair(0U, &WebAssembly::I64RegClass);
492  }
493  break;
494  default:
495  break;
496  }
497  }
498 
499  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
500 }
501 
502 bool WebAssemblyTargetLowering::isCheapToSpeculateCttz() const {
503  // Assume ctz is a relatively cheap operation.
504  return true;
505 }
506 
507 bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz() const {
508  // Assume clz is a relatively cheap operation.
509  return true;
510 }
511 
512 bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
513  const AddrMode &AM,
514  Type *Ty, unsigned AS,
515  Instruction *I) const {
516  // WebAssembly offsets are added as unsigned without wrapping. The
517  // isLegalAddressingMode gives us no way to determine if wrapping could be
518  // happening, so we approximate this by accepting only non-negative offsets.
519  if (AM.BaseOffs < 0)
520  return false;
521 
522  // WebAssembly has no scale register operands.
523  if (AM.Scale != 0)
524  return false;
525 
526  // Everything else is legal.
527  return true;
528 }
529 
530 bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses(
531  EVT /*VT*/, unsigned /*AddrSpace*/, unsigned /*Align*/,
532  MachineMemOperand::Flags /*Flags*/, bool *Fast) const {
533  // WebAssembly supports unaligned accesses, though it should be declared
534  // with the p2align attribute on loads and stores which do so, and there
535  // may be a performance impact. We tell LLVM they're "fast" because
536  // for the kinds of things that LLVM uses this for (merging adjacent stores
537  // of constants, etc.), WebAssembly implementations will either want the
538  // unaligned access or they'll split anyway.
539  if (Fast)
540  *Fast = true;
541  return true;
542 }
543 
544 bool WebAssemblyTargetLowering::isIntDivCheap(EVT VT,
545  AttributeList Attr) const {
546  // The current thinking is that wasm engines will perform this optimization,
547  // so we can save on code size.
548  return true;
549 }
550 
551 bool WebAssemblyTargetLowering::isVectorLoadExtDesirable(SDValue ExtVal) const {
552  if (!Subtarget->hasUnimplementedSIMD128())
553  return false;
554  MVT ExtT = ExtVal.getSimpleValueType();
555  MVT MemT = cast<LoadSDNode>(ExtVal->getOperand(0))->getSimpleValueType(0);
556  return (ExtT == MVT::v8i16 && MemT == MVT::v8i8) ||
557  (ExtT == MVT::v4i32 && MemT == MVT::v4i16) ||
558  (ExtT == MVT::v2i64 && MemT == MVT::v2i32);
559 }
560 
561 EVT WebAssemblyTargetLowering::getSetCCResultType(const DataLayout &DL,
562  LLVMContext &C,
563  EVT VT) const {
564  if (VT.isVector())
566 
567  return TargetLowering::getSetCCResultType(DL, C, VT);
568 }
569 
570 bool WebAssemblyTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
571  const CallInst &I,
572  MachineFunction &MF,
573  unsigned Intrinsic) const {
574  switch (Intrinsic) {
575  case Intrinsic::wasm_atomic_notify:
577  Info.memVT = MVT::i32;
578  Info.ptrVal = I.getArgOperand(0);
579  Info.offset = 0;
580  Info.align = Align(4);
581  // atomic.notify instruction does not really load the memory specified with
582  // this argument, but MachineMemOperand should either be load or store, so
583  // we set this to a load.
584  // FIXME Volatile isn't really correct, but currently all LLVM atomic
585  // instructions are treated as volatiles in the backend, so we should be
586  // consistent. The same applies for wasm_atomic_wait intrinsics too.
588  return true;
589  case Intrinsic::wasm_atomic_wait_i32:
591  Info.memVT = MVT::i32;
592  Info.ptrVal = I.getArgOperand(0);
593  Info.offset = 0;
594  Info.align = Align(4);
596  return true;
597  case Intrinsic::wasm_atomic_wait_i64:
599  Info.memVT = MVT::i64;
600  Info.ptrVal = I.getArgOperand(0);
601  Info.offset = 0;
602  Info.align = Align(8);
604  return true;
605  default:
606  return false;
607  }
608 }
609 
610 //===----------------------------------------------------------------------===//
611 // WebAssembly Lowering private implementation.
612 //===----------------------------------------------------------------------===//
613 
614 //===----------------------------------------------------------------------===//
615 // Lowering Code
616 //===----------------------------------------------------------------------===//
617 
618 static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *Msg) {
620  DAG.getContext()->diagnose(
622 }
623 
624 // Test whether the given calling convention is supported.
625 static bool callingConvSupported(CallingConv::ID CallConv) {
626  // We currently support the language-independent target-independent
627  // conventions. We don't yet have a way to annotate calls with properties like
628  // "cold", and we don't have any call-clobbered registers, so these are mostly
629  // all handled the same.
630  return CallConv == CallingConv::C || CallConv == CallingConv::Fast ||
631  CallConv == CallingConv::Cold ||
632  CallConv == CallingConv::PreserveMost ||
633  CallConv == CallingConv::PreserveAll ||
634  CallConv == CallingConv::CXX_FAST_TLS ||
636 }
637 
638 SDValue
639 WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
640  SmallVectorImpl<SDValue> &InVals) const {
641  SelectionDAG &DAG = CLI.DAG;
642  SDLoc DL = CLI.DL;
643  SDValue Chain = CLI.Chain;
644  SDValue Callee = CLI.Callee;
646  auto Layout = MF.getDataLayout();
647 
648  CallingConv::ID CallConv = CLI.CallConv;
649  if (!callingConvSupported(CallConv))
650  fail(DL, DAG,
651  "WebAssembly doesn't support language-specific or target-specific "
652  "calling conventions yet");
653  if (CLI.IsPatchPoint)
654  fail(DL, DAG, "WebAssembly doesn't support patch point yet");
655 
656  if (CLI.IsTailCall) {
657  bool MustTail = CLI.CS && CLI.CS.isMustTailCall();
658  if (Subtarget->hasTailCall() && !CLI.IsVarArg) {
659  // Do not tail call unless caller and callee return types match
660  const Function &F = MF.getFunction();
661  const TargetMachine &TM = getTargetMachine();
662  Type *RetTy = F.getReturnType();
663  SmallVector<MVT, 4> CallerRetTys;
664  SmallVector<MVT, 4> CalleeRetTys;
665  computeLegalValueVTs(F, TM, RetTy, CallerRetTys);
666  computeLegalValueVTs(F, TM, CLI.RetTy, CalleeRetTys);
667  bool TypesMatch = CallerRetTys.size() == CalleeRetTys.size() &&
668  std::equal(CallerRetTys.begin(), CallerRetTys.end(),
669  CalleeRetTys.begin());
670  if (!TypesMatch) {
671  // musttail in this case would be an LLVM IR validation failure
672  assert(!MustTail);
673  CLI.IsTailCall = false;
674  }
675  } else {
676  CLI.IsTailCall = false;
677  if (MustTail) {
678  if (CLI.IsVarArg) {
679  // The return would pop the argument buffer
680  fail(DL, DAG, "WebAssembly does not support varargs tail calls");
681  } else {
682  fail(DL, DAG, "WebAssembly 'tail-call' feature not enabled");
683  }
684  }
685  }
686  }
687 
689  if (Ins.size() > 1)
690  fail(DL, DAG, "WebAssembly doesn't support more than 1 returned value yet");
691 
692  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
693  SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
694 
695  // The generic code may have added an sret argument. If we're lowering an
696  // invoke function, the ABI requires that the function pointer be the first
697  // argument, so we may have to swap the arguments.
698  if (CallConv == CallingConv::WASM_EmscriptenInvoke && Outs.size() >= 2 &&
699  Outs[0].Flags.isSRet()) {
700  std::swap(Outs[0], Outs[1]);
701  std::swap(OutVals[0], OutVals[1]);
702  }
703 
704  unsigned NumFixedArgs = 0;
705  for (unsigned I = 0; I < Outs.size(); ++I) {
706  const ISD::OutputArg &Out = Outs[I];
707  SDValue &OutVal = OutVals[I];
708  if (Out.Flags.isNest())
709  fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
710  if (Out.Flags.isInAlloca())
711  fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
712  if (Out.Flags.isInConsecutiveRegs())
713  fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
714  if (Out.Flags.isInConsecutiveRegsLast())
715  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
716  if (Out.Flags.isByVal() && Out.Flags.getByValSize() != 0) {
717  auto &MFI = MF.getFrameInfo();
718  int FI = MFI.CreateStackObject(Out.Flags.getByValSize(),
719  Out.Flags.getByValAlign(),
720  /*isSS=*/false);
721  SDValue SizeNode =
722  DAG.getConstant(Out.Flags.getByValSize(), DL, MVT::i32);
723  SDValue FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
724  Chain = DAG.getMemcpy(
725  Chain, DL, FINode, OutVal, SizeNode, Out.Flags.getByValAlign(),
726  /*isVolatile*/ false, /*AlwaysInline=*/false,
727  /*isTailCall*/ false, MachinePointerInfo(), MachinePointerInfo());
728  OutVal = FINode;
729  }
730  // Count the number of fixed args *after* legalization.
731  NumFixedArgs += Out.IsFixed;
732  }
733 
734  bool IsVarArg = CLI.IsVarArg;
735  auto PtrVT = getPointerTy(Layout);
736 
737  // Analyze operands of the call, assigning locations to each operand.
739  CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
740 
741  if (IsVarArg) {
742  // Outgoing non-fixed arguments are placed in a buffer. First
743  // compute their offsets and the total amount of buffer space needed.
744  for (unsigned I = NumFixedArgs; I < Outs.size(); ++I) {
745  const ISD::OutputArg &Out = Outs[I];
746  SDValue &Arg = OutVals[I];
747  EVT VT = Arg.getValueType();
748  assert(VT != MVT::iPTR && "Legalized args should be concrete");
749  Type *Ty = VT.getTypeForEVT(*DAG.getContext());
750  unsigned Align = std::max(Out.Flags.getOrigAlign(),
751  Layout.getABITypeAlignment(Ty));
752  unsigned Offset = CCInfo.AllocateStack(Layout.getTypeAllocSize(Ty),
753  Align);
754  CCInfo.addLoc(CCValAssign::getMem(ArgLocs.size(), VT.getSimpleVT(),
755  Offset, VT.getSimpleVT(),
757  }
758  }
759 
760  unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
761 
762  SDValue FINode;
763  if (IsVarArg && NumBytes) {
764  // For non-fixed arguments, next emit stores to store the argument values
765  // to the stack buffer at the offsets computed above.
766  int FI = MF.getFrameInfo().CreateStackObject(NumBytes,
767  Layout.getStackAlignment(),
768  /*isSS=*/false);
769  unsigned ValNo = 0;
771  for (SDValue Arg :
772  make_range(OutVals.begin() + NumFixedArgs, OutVals.end())) {
773  assert(ArgLocs[ValNo].getValNo() == ValNo &&
774  "ArgLocs should remain in order and only hold varargs args");
775  unsigned Offset = ArgLocs[ValNo++].getLocMemOffset();
776  FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
777  SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, FINode,
778  DAG.getConstant(Offset, DL, PtrVT));
779  Chains.push_back(
780  DAG.getStore(Chain, DL, Arg, Add,
781  MachinePointerInfo::getFixedStack(MF, FI, Offset), 0));
782  }
783  if (!Chains.empty())
784  Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
785  } else if (IsVarArg) {
786  FINode = DAG.getIntPtrConstant(0, DL);
787  }
788 
789  if (Callee->getOpcode() == ISD::GlobalAddress) {
790  // If the callee is a GlobalAddress node (quite common, every direct call
791  // is) turn it into a TargetGlobalAddress node so that LowerGlobalAddress
792  // doesn't at MO_GOT which is not needed for direct calls.
793  GlobalAddressSDNode* GA = cast<GlobalAddressSDNode>(Callee);
794  Callee = DAG.getTargetGlobalAddress(GA->getGlobal(), DL,
796  GA->getOffset());
797  Callee = DAG.getNode(WebAssemblyISD::Wrapper, DL,
798  getPointerTy(DAG.getDataLayout()), Callee);
799  }
800 
801  // Compute the operands for the CALLn node.
803  Ops.push_back(Chain);
804  Ops.push_back(Callee);
805 
806  // Add all fixed arguments. Note that for non-varargs calls, NumFixedArgs
807  // isn't reliable.
808  Ops.append(OutVals.begin(),
809  IsVarArg ? OutVals.begin() + NumFixedArgs : OutVals.end());
810  // Add a pointer to the vararg buffer.
811  if (IsVarArg)
812  Ops.push_back(FINode);
813 
814  SmallVector<EVT, 8> InTys;
815  for (const auto &In : Ins) {
816  assert(!In.Flags.isByVal() && "byval is not valid for return values");
817  assert(!In.Flags.isNest() && "nest is not valid for return values");
818  if (In.Flags.isInAlloca())
819  fail(DL, DAG, "WebAssembly hasn't implemented inalloca return values");
820  if (In.Flags.isInConsecutiveRegs())
821  fail(DL, DAG, "WebAssembly hasn't implemented cons regs return values");
822  if (In.Flags.isInConsecutiveRegsLast())
823  fail(DL, DAG,
824  "WebAssembly hasn't implemented cons regs last return values");
825  // Ignore In.getOrigAlign() because all our arguments are passed in
826  // registers.
827  InTys.push_back(In.VT);
828  }
829 
830  if (CLI.IsTailCall) {
831  // ret_calls do not return values to the current frame
832  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
833  return DAG.getNode(WebAssemblyISD::RET_CALL, DL, NodeTys, Ops);
834  }
835 
836  InTys.push_back(MVT::Other);
837  SDVTList InTyList = DAG.getVTList(InTys);
838  SDValue Res =
839  DAG.getNode(Ins.empty() ? WebAssemblyISD::CALL0 : WebAssemblyISD::CALL1,
840  DL, InTyList, Ops);
841  if (Ins.empty()) {
842  Chain = Res;
843  } else {
844  InVals.push_back(Res);
845  Chain = Res.getValue(1);
846  }
847 
848  return Chain;
849 }
850 
851 bool WebAssemblyTargetLowering::CanLowerReturn(
852  CallingConv::ID /*CallConv*/, MachineFunction & /*MF*/, bool /*IsVarArg*/,
854  LLVMContext & /*Context*/) const {
855  // WebAssembly can only handle returning tuples with multivalue enabled
856  return Subtarget->hasMultivalue() || Outs.size() <= 1;
857 }
858 
859 SDValue WebAssemblyTargetLowering::LowerReturn(
860  SDValue Chain, CallingConv::ID CallConv, bool /*IsVarArg*/,
862  const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
863  SelectionDAG &DAG) const {
864  assert((Subtarget->hasMultivalue() || Outs.size() <= 1) &&
865  "MVP WebAssembly can only return up to one value");
866  if (!callingConvSupported(CallConv))
867  fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
868 
869  SmallVector<SDValue, 4> RetOps(1, Chain);
870  RetOps.append(OutVals.begin(), OutVals.end());
871  Chain = DAG.getNode(WebAssemblyISD::RETURN, DL, MVT::Other, RetOps);
872 
873  // Record the number and types of the return values.
874  for (const ISD::OutputArg &Out : Outs) {
875  assert(!Out.Flags.isByVal() && "byval is not valid for return values");
876  assert(!Out.Flags.isNest() && "nest is not valid for return values");
877  assert(Out.IsFixed && "non-fixed return value is not valid");
878  if (Out.Flags.isInAlloca())
879  fail(DL, DAG, "WebAssembly hasn't implemented inalloca results");
880  if (Out.Flags.isInConsecutiveRegs())
881  fail(DL, DAG, "WebAssembly hasn't implemented cons regs results");
882  if (Out.Flags.isInConsecutiveRegsLast())
883  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last results");
884  }
885 
886  return Chain;
887 }
888 
889 SDValue WebAssemblyTargetLowering::LowerFormalArguments(
890  SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
891  const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
892  SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
893  if (!callingConvSupported(CallConv))
894  fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
895 
897  auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
898 
899  // Set up the incoming ARGUMENTS value, which serves to represent the liveness
900  // of the incoming values before they're represented by virtual registers.
901  MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
902 
903  for (const ISD::InputArg &In : Ins) {
904  if (In.Flags.isInAlloca())
905  fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
906  if (In.Flags.isNest())
907  fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
908  if (In.Flags.isInConsecutiveRegs())
909  fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
910  if (In.Flags.isInConsecutiveRegsLast())
911  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
912  // Ignore In.getOrigAlign() because all our arguments are passed in
913  // registers.
914  InVals.push_back(In.Used ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
915  DAG.getTargetConstant(InVals.size(),
916  DL, MVT::i32))
917  : DAG.getUNDEF(In.VT));
918 
919  // Record the number and types of arguments.
920  MFI->addParam(In.VT);
921  }
922 
923  // Varargs are copied into a buffer allocated by the caller, and a pointer to
924  // the buffer is passed as an argument.
925  if (IsVarArg) {
926  MVT PtrVT = getPointerTy(MF.getDataLayout());
927  Register VarargVreg =
929  MFI->setVarargBufferVreg(VarargVreg);
930  Chain = DAG.getCopyToReg(
931  Chain, DL, VarargVreg,
932  DAG.getNode(WebAssemblyISD::ARGUMENT, DL, PtrVT,
933  DAG.getTargetConstant(Ins.size(), DL, MVT::i32)));
934  MFI->addParam(PtrVT);
935  }
936 
937  // Record the number and types of arguments and results.
938  SmallVector<MVT, 4> Params;
941  DAG.getTarget(), Params, Results);
942  for (MVT VT : Results)
943  MFI->addResult(VT);
944  // TODO: Use signatures in WebAssemblyMachineFunctionInfo too and unify
945  // the param logic here with ComputeSignatureVTs
946  assert(MFI->getParams().size() == Params.size() &&
947  std::equal(MFI->getParams().begin(), MFI->getParams().end(),
948  Params.begin()));
949 
950  return Chain;
951 }
952 
953 void WebAssemblyTargetLowering::ReplaceNodeResults(
955  switch (N->getOpcode()) {
957  // Do not add any results, signifying that N should not be custom lowered
958  // after all. This happens because simd128 turns on custom lowering for
959  // SIGN_EXTEND_INREG, but for non-vector sign extends the result might be an
960  // illegal type.
961  break;
962  default:
964  "ReplaceNodeResults not implemented for this op for WebAssembly!");
965  }
966 }
967 
968 //===----------------------------------------------------------------------===//
969 // Custom lowering hooks.
970 //===----------------------------------------------------------------------===//
971 
972 SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
973  SelectionDAG &DAG) const {
974  SDLoc DL(Op);
975  switch (Op.getOpcode()) {
976  default:
977  llvm_unreachable("unimplemented operation lowering");
978  return SDValue();
979  case ISD::FrameIndex:
980  return LowerFrameIndex(Op, DAG);
981  case ISD::GlobalAddress:
982  return LowerGlobalAddress(Op, DAG);
983  case ISD::ExternalSymbol:
984  return LowerExternalSymbol(Op, DAG);
985  case ISD::JumpTable:
986  return LowerJumpTable(Op, DAG);
987  case ISD::BR_JT:
988  return LowerBR_JT(Op, DAG);
989  case ISD::VASTART:
990  return LowerVASTART(Op, DAG);
991  case ISD::BlockAddress:
992  case ISD::BRIND:
993  fail(DL, DAG, "WebAssembly hasn't implemented computed gotos");
994  return SDValue();
995  case ISD::RETURNADDR:
996  return LowerRETURNADDR(Op, DAG);
997  case ISD::FRAMEADDR:
998  return LowerFRAMEADDR(Op, DAG);
999  case ISD::CopyToReg:
1000  return LowerCopyToReg(Op, DAG);
1003  return LowerAccessVectorElement(Op, DAG);
1004  case ISD::INTRINSIC_VOID:
1007  return LowerIntrinsic(Op, DAG);
1009  return LowerSIGN_EXTEND_INREG(Op, DAG);
1010  case ISD::BUILD_VECTOR:
1011  return LowerBUILD_VECTOR(Op, DAG);
1012  case ISD::VECTOR_SHUFFLE:
1013  return LowerVECTOR_SHUFFLE(Op, DAG);
1014  case ISD::SHL:
1015  case ISD::SRA:
1016  case ISD::SRL:
1017  return LowerShift(Op, DAG);
1018  }
1019 }
1020 
1021 SDValue WebAssemblyTargetLowering::LowerCopyToReg(SDValue Op,
1022  SelectionDAG &DAG) const {
1023  SDValue Src = Op.getOperand(2);
1024  if (isa<FrameIndexSDNode>(Src.getNode())) {
1025  // CopyToReg nodes don't support FrameIndex operands. Other targets select
1026  // the FI to some LEA-like instruction, but since we don't have that, we
1027  // need to insert some kind of instruction that can take an FI operand and
1028  // produces a value usable by CopyToReg (i.e. in a vreg). So insert a dummy
1029  // local.copy between Op and its FI operand.
1030  SDValue Chain = Op.getOperand(0);
1031  SDLoc DL(Op);
1032  unsigned Reg = cast<RegisterSDNode>(Op.getOperand(1))->getReg();
1033  EVT VT = Src.getValueType();
1034  SDValue Copy(DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32
1035  : WebAssembly::COPY_I64,
1036  DL, VT, Src),
1037  0);
1038  return Op.getNode()->getNumValues() == 1
1039  ? DAG.getCopyToReg(Chain, DL, Reg, Copy)
1040  : DAG.getCopyToReg(Chain, DL, Reg, Copy,
1041  Op.getNumOperands() == 4 ? Op.getOperand(3)
1042  : SDValue());
1043  }
1044  return SDValue();
1045 }
1046 
1047 SDValue WebAssemblyTargetLowering::LowerFrameIndex(SDValue Op,
1048  SelectionDAG &DAG) const {
1049  int FI = cast<FrameIndexSDNode>(Op)->getIndex();
1050  return DAG.getTargetFrameIndex(FI, Op.getValueType());
1051 }
1052 
1053 SDValue WebAssemblyTargetLowering::LowerRETURNADDR(SDValue Op,
1054  SelectionDAG &DAG) const {
1055  SDLoc DL(Op);
1056 
1057  if (!Subtarget->getTargetTriple().isOSEmscripten()) {
1058  fail(DL, DAG,
1059  "Non-Emscripten WebAssembly hasn't implemented "
1060  "__builtin_return_address");
1061  return SDValue();
1062  }
1063 
1065  return SDValue();
1066 
1067  unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
1068  MakeLibCallOptions CallOptions;
1069  return makeLibCall(DAG, RTLIB::RETURN_ADDRESS, Op.getValueType(),
1070  {DAG.getConstant(Depth, DL, MVT::i32)}, CallOptions, DL)
1071  .first;
1072 }
1073 
1074 SDValue WebAssemblyTargetLowering::LowerFRAMEADDR(SDValue Op,
1075  SelectionDAG &DAG) const {
1076  // Non-zero depths are not supported by WebAssembly currently. Use the
1077  // legalizer's default expansion, which is to return 0 (what this function is
1078  // documented to do).
1079  if (Op.getConstantOperandVal(0) > 0)
1080  return SDValue();
1081 
1083  EVT VT = Op.getValueType();
1084  Register FP =
1086  return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), FP, VT);
1087 }
1088 
1089 SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
1090  SelectionDAG &DAG) const {
1091  SDLoc DL(Op);
1092  const auto *GA = cast<GlobalAddressSDNode>(Op);
1093  EVT VT = Op.getValueType();
1094  assert(GA->getTargetFlags() == 0 &&
1095  "Unexpected target flags on generic GlobalAddressSDNode");
1096  if (GA->getAddressSpace() != 0)
1097  fail(DL, DAG, "WebAssembly only expects the 0 address space");
1098 
1099  unsigned OperandFlags = 0;
1100  if (isPositionIndependent()) {
1101  const GlobalValue *GV = GA->getGlobal();
1102  if (getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV)) {
1103  MachineFunction &MF = DAG.getMachineFunction();
1104  MVT PtrVT = getPointerTy(MF.getDataLayout());
1105  const char *BaseName;
1106  if (GV->getValueType()->isFunctionTy()) {
1107  BaseName = MF.createExternalSymbolName("__table_base");
1108  OperandFlags = WebAssemblyII::MO_TABLE_BASE_REL;
1109  }
1110  else {
1111  BaseName = MF.createExternalSymbolName("__memory_base");
1112  OperandFlags = WebAssemblyII::MO_MEMORY_BASE_REL;
1113  }
1114  SDValue BaseAddr =
1115  DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT,
1116  DAG.getTargetExternalSymbol(BaseName, PtrVT));
1117 
1118  SDValue SymAddr = DAG.getNode(
1120  DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset(),
1121  OperandFlags));
1122 
1123  return DAG.getNode(ISD::ADD, DL, VT, BaseAddr, SymAddr);
1124  } else {
1125  OperandFlags = WebAssemblyII::MO_GOT;
1126  }
1127  }
1128 
1129  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1130  DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT,
1131  GA->getOffset(), OperandFlags));
1132 }
1133 
1134 SDValue
1135 WebAssemblyTargetLowering::LowerExternalSymbol(SDValue Op,
1136  SelectionDAG &DAG) const {
1137  SDLoc DL(Op);
1138  const auto *ES = cast<ExternalSymbolSDNode>(Op);
1139  EVT VT = Op.getValueType();
1140  assert(ES->getTargetFlags() == 0 &&
1141  "Unexpected target flags on generic ExternalSymbolSDNode");
1142  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1143  DAG.getTargetExternalSymbol(ES->getSymbol(), VT));
1144 }
1145 
1146 SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op,
1147  SelectionDAG &DAG) const {
1148  // There's no need for a Wrapper node because we always incorporate a jump
1149  // table operand into a BR_TABLE instruction, rather than ever
1150  // materializing it in a register.
1151  const JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
1152  return DAG.getTargetJumpTable(JT->getIndex(), Op.getValueType(),
1153  JT->getTargetFlags());
1154 }
1155 
1156 SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op,
1157  SelectionDAG &DAG) const {
1158  SDLoc DL(Op);
1159  SDValue Chain = Op.getOperand(0);
1160  const auto *JT = cast<JumpTableSDNode>(Op.getOperand(1));
1161  SDValue Index = Op.getOperand(2);
1162  assert(JT->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");
1163 
1165  Ops.push_back(Chain);
1166  Ops.push_back(Index);
1167 
1169  const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs;
1170 
1171  // Add an operand for each case.
1172  for (auto MBB : MBBs)
1173  Ops.push_back(DAG.getBasicBlock(MBB));
1174 
1175  // TODO: For now, we just pick something arbitrary for a default case for now.
1176  // We really want to sniff out the guard and put in the real default case (and
1177  // delete the guard).
1178  Ops.push_back(DAG.getBasicBlock(MBBs[0]));
1179 
1180  return DAG.getNode(WebAssemblyISD::BR_TABLE, DL, MVT::Other, Ops);
1181 }
1182 
1183 SDValue WebAssemblyTargetLowering::LowerVASTART(SDValue Op,
1184  SelectionDAG &DAG) const {
1185  SDLoc DL(Op);
1187 
1188  auto *MFI = DAG.getMachineFunction().getInfo<WebAssemblyFunctionInfo>();
1189  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
1190 
1191  SDValue ArgN = DAG.getCopyFromReg(DAG.getEntryNode(), DL,
1192  MFI->getVarargBufferVreg(), PtrVT);
1193  return DAG.getStore(Op.getOperand(0), DL, ArgN, Op.getOperand(1),
1194  MachinePointerInfo(SV), 0);
1195 }
1196 
1197 SDValue WebAssemblyTargetLowering::LowerIntrinsic(SDValue Op,
1198  SelectionDAG &DAG) const {
1199  MachineFunction &MF = DAG.getMachineFunction();
1200  unsigned IntNo;
1201  switch (Op.getOpcode()) {
1202  case ISD::INTRINSIC_VOID:
1204  IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
1205  break;
1207  IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
1208  break;
1209  default:
1210  llvm_unreachable("Invalid intrinsic");
1211  }
1212  SDLoc DL(Op);
1213 
1214  switch (IntNo) {
1215  default:
1216  return SDValue(); // Don't custom lower most intrinsics.
1217 
1218  case Intrinsic::wasm_lsda: {
1219  EVT VT = Op.getValueType();
1220  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1221  MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
1222  auto &Context = MF.getMMI().getContext();
1223  MCSymbol *S = Context.getOrCreateSymbol(Twine("GCC_except_table") +
1224  Twine(MF.getFunctionNumber()));
1225  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1226  DAG.getMCSymbol(S, PtrVT));
1227  }
1228 
1229  case Intrinsic::wasm_throw: {
1230  // We only support C++ exceptions for now
1231  int Tag = cast<ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue();
1232  if (Tag != CPP_EXCEPTION)
1233  llvm_unreachable("Invalid tag!");
1234  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1235  MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
1236  const char *SymName = MF.createExternalSymbolName("__cpp_exception");
1237  SDValue SymNode = DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT,
1238  DAG.getTargetExternalSymbol(SymName, PtrVT));
1239  return DAG.getNode(WebAssemblyISD::THROW, DL,
1240  MVT::Other, // outchain type
1241  {
1242  Op.getOperand(0), // inchain
1243  SymNode, // exception symbol
1244  Op.getOperand(3) // thrown value
1245  });
1246  }
1247  }
1248 }
1249 
1250 SDValue
1251 WebAssemblyTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
1252  SelectionDAG &DAG) const {
1253  SDLoc DL(Op);
1254  // If sign extension operations are disabled, allow sext_inreg only if operand
1255  // is a vector extract. SIMD does not depend on sign extension operations, but
1256  // allowing sext_inreg in this context lets us have simple patterns to select
1257  // extract_lane_s instructions. Expanding sext_inreg everywhere would be
1258  // simpler in this file, but would necessitate large and brittle patterns to
1259  // undo the expansion and select extract_lane_s instructions.
1260  assert(!Subtarget->hasSignExt() && Subtarget->hasSIMD128());
1261  if (Op.getOperand(0).getOpcode() == ISD::EXTRACT_VECTOR_ELT) {
1262  const SDValue &Extract = Op.getOperand(0);
1263  MVT VecT = Extract.getOperand(0).getSimpleValueType();
1264  MVT ExtractedLaneT = static_cast<VTSDNode *>(Op.getOperand(1).getNode())
1265  ->getVT()
1266  .getSimpleVT();
1267  MVT ExtractedVecT =
1268  MVT::getVectorVT(ExtractedLaneT, 128 / ExtractedLaneT.getSizeInBits());
1269  if (ExtractedVecT == VecT)
1270  return Op;
1271  // Bitcast vector to appropriate type to ensure ISel pattern coverage
1272  const SDValue &Index = Extract.getOperand(1);
1273  unsigned IndexVal =
1274  static_cast<ConstantSDNode *>(Index.getNode())->getZExtValue();
1275  unsigned Scale =
1276  ExtractedVecT.getVectorNumElements() / VecT.getVectorNumElements();
1277  assert(Scale > 1);
1278  SDValue NewIndex =
1279  DAG.getConstant(IndexVal * Scale, DL, Index.getValueType());
1280  SDValue NewExtract = DAG.getNode(
1281  ISD::EXTRACT_VECTOR_ELT, DL, Extract.getValueType(),
1282  DAG.getBitcast(ExtractedVecT, Extract.getOperand(0)), NewIndex);
1283  return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, Op.getValueType(),
1284  NewExtract, Op.getOperand(1));
1285  }
1286  // Otherwise expand
1287  return SDValue();
1288 }
1289 
1290 SDValue WebAssemblyTargetLowering::LowerBUILD_VECTOR(SDValue Op,
1291  SelectionDAG &DAG) const {
1292  SDLoc DL(Op);
1293  const EVT VecT = Op.getValueType();
1294  const EVT LaneT = Op.getOperand(0).getValueType();
1295  const size_t Lanes = Op.getNumOperands();
1296  bool CanSwizzle = Subtarget->hasUnimplementedSIMD128() && VecT == MVT::v16i8;
1297 
1298  // BUILD_VECTORs are lowered to the instruction that initializes the highest
1299  // possible number of lanes at once followed by a sequence of replace_lane
1300  // instructions to individually initialize any remaining lanes.
1301 
1302  // TODO: Tune this. For example, lanewise swizzling is very expensive, so
1303  // swizzled lanes should be given greater weight.
1304 
1305  // TODO: Investigate building vectors by shuffling together vectors built by
1306  // separately specialized means.
1307 
1308  auto IsConstant = [](const SDValue &V) {
1309  return V.getOpcode() == ISD::Constant || V.getOpcode() == ISD::ConstantFP;
1310  };
1311 
1312  // Returns the source vector and index vector pair if they exist. Checks for:
1313  // (extract_vector_elt
1314  // $src,
1315  // (sign_extend_inreg (extract_vector_elt $indices, $i))
1316  // )
1317  auto GetSwizzleSrcs = [](size_t I, const SDValue &Lane) {
1318  auto Bail = std::make_pair(SDValue(), SDValue());
1319  if (Lane->getOpcode() != ISD::EXTRACT_VECTOR_ELT)
1320  return Bail;
1321  const SDValue &SwizzleSrc = Lane->getOperand(0);
1322  const SDValue &IndexExt = Lane->getOperand(1);
1323  if (IndexExt->getOpcode() != ISD::SIGN_EXTEND_INREG)
1324  return Bail;
1325  const SDValue &Index = IndexExt->getOperand(0);
1326  if (Index->getOpcode() != ISD::EXTRACT_VECTOR_ELT)
1327  return Bail;
1328  const SDValue &SwizzleIndices = Index->getOperand(0);
1329  if (SwizzleSrc.getValueType() != MVT::v16i8 ||
1330  SwizzleIndices.getValueType() != MVT::v16i8 ||
1331  Index->getOperand(1)->getOpcode() != ISD::Constant ||
1332  Index->getConstantOperandVal(1) != I)
1333  return Bail;
1334  return std::make_pair(SwizzleSrc, SwizzleIndices);
1335  };
1336 
1337  using ValueEntry = std::pair<SDValue, size_t>;
1338  SmallVector<ValueEntry, 16> SplatValueCounts;
1339 
1340  using SwizzleEntry = std::pair<std::pair<SDValue, SDValue>, size_t>;
1341  SmallVector<SwizzleEntry, 16> SwizzleCounts;
1342 
1343  auto AddCount = [](auto &Counts, const auto &Val) {
1344  auto CountIt = std::find_if(Counts.begin(), Counts.end(),
1345  [&Val](auto E) { return E.first == Val; });
1346  if (CountIt == Counts.end()) {
1347  Counts.emplace_back(Val, 1);
1348  } else {
1349  CountIt->second++;
1350  }
1351  };
1352 
1353  auto GetMostCommon = [](auto &Counts) {
1354  auto CommonIt =
1355  std::max_element(Counts.begin(), Counts.end(),
1356  [](auto A, auto B) { return A.second < B.second; });
1357  assert(CommonIt != Counts.end() && "Unexpected all-undef build_vector");
1358  return *CommonIt;
1359  };
1360 
1361  size_t NumConstantLanes = 0;
1362 
1363  // Count eligible lanes for each type of vector creation op
1364  for (size_t I = 0; I < Lanes; ++I) {
1365  const SDValue &Lane = Op->getOperand(I);
1366  if (Lane.isUndef())
1367  continue;
1368 
1369  AddCount(SplatValueCounts, Lane);
1370 
1371  if (IsConstant(Lane)) {
1372  NumConstantLanes++;
1373  } else if (CanSwizzle) {
1374  auto SwizzleSrcs = GetSwizzleSrcs(I, Lane);
1375  if (SwizzleSrcs.first)
1376  AddCount(SwizzleCounts, SwizzleSrcs);
1377  }
1378  }
1379 
1380  SDValue SplatValue;
1381  size_t NumSplatLanes;
1382  std::tie(SplatValue, NumSplatLanes) = GetMostCommon(SplatValueCounts);
1383 
1384  SDValue SwizzleSrc;
1385  SDValue SwizzleIndices;
1386  size_t NumSwizzleLanes = 0;
1387  if (SwizzleCounts.size())
1388  std::forward_as_tuple(std::tie(SwizzleSrc, SwizzleIndices),
1389  NumSwizzleLanes) = GetMostCommon(SwizzleCounts);
1390 
1391  // Predicate returning true if the lane is properly initialized by the
1392  // original instruction
1393  std::function<bool(size_t, const SDValue &)> IsLaneConstructed;
1394  SDValue Result;
1395  if (Subtarget->hasUnimplementedSIMD128()) {
1396  // Prefer swizzles over vector consts over splats
1397  if (NumSwizzleLanes >= NumSplatLanes &&
1398  NumSwizzleLanes >= NumConstantLanes) {
1399  Result = DAG.getNode(WebAssemblyISD::SWIZZLE, DL, VecT, SwizzleSrc,
1400  SwizzleIndices);
1401  auto Swizzled = std::make_pair(SwizzleSrc, SwizzleIndices);
1402  IsLaneConstructed = [&, Swizzled](size_t I, const SDValue &Lane) {
1403  return Swizzled == GetSwizzleSrcs(I, Lane);
1404  };
1405  } else if (NumConstantLanes >= NumSplatLanes) {
1406  SmallVector<SDValue, 16> ConstLanes;
1407  for (const SDValue &Lane : Op->op_values()) {
1408  if (IsConstant(Lane)) {
1409  ConstLanes.push_back(Lane);
1410  } else if (LaneT.isFloatingPoint()) {
1411  ConstLanes.push_back(DAG.getConstantFP(0, DL, LaneT));
1412  } else {
1413  ConstLanes.push_back(DAG.getConstant(0, DL, LaneT));
1414  }
1415  }
1416  Result = DAG.getBuildVector(VecT, DL, ConstLanes);
1417  IsLaneConstructed = [&](size_t _, const SDValue &Lane) {
1418  return IsConstant(Lane);
1419  };
1420  }
1421  }
1422  if (!Result) {
1423  // Use a splat, but possibly a load_splat
1424  LoadSDNode *SplattedLoad;
1425  if (Subtarget->hasUnimplementedSIMD128() &&
1426  (SplattedLoad = dyn_cast<LoadSDNode>(SplatValue)) &&
1427  SplattedLoad->getMemoryVT() == VecT.getVectorElementType()) {
1428  Result = DAG.getNode(WebAssemblyISD::LOAD_SPLAT, DL, VecT, SplatValue);
1429  } else {
1430  Result = DAG.getSplatBuildVector(VecT, DL, SplatValue);
1431  }
1432  IsLaneConstructed = [&](size_t _, const SDValue &Lane) {
1433  return Lane == SplatValue;
1434  };
1435  }
1436 
1437  // Add replace_lane instructions for any unhandled values
1438  for (size_t I = 0; I < Lanes; ++I) {
1439  const SDValue &Lane = Op->getOperand(I);
1440  if (!Lane.isUndef() && !IsLaneConstructed(I, Lane))
1441  Result = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VecT, Result, Lane,
1442  DAG.getConstant(I, DL, MVT::i32));
1443  }
1444 
1445  return Result;
1446 }
1447 
1448 SDValue
1449 WebAssemblyTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
1450  SelectionDAG &DAG) const {
1451  SDLoc DL(Op);
1452  ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(Op.getNode())->getMask();
1454  assert(VecType.is128BitVector() && "Unexpected shuffle vector type");
1455  size_t LaneBytes = VecType.getVectorElementType().getSizeInBits() / 8;
1456 
1457  // Space for two vector args and sixteen mask indices
1458  SDValue Ops[18];
1459  size_t OpIdx = 0;
1460  Ops[OpIdx++] = Op.getOperand(0);
1461  Ops[OpIdx++] = Op.getOperand(1);
1462 
1463  // Expand mask indices to byte indices and materialize them as operands
1464  for (int M : Mask) {
1465  for (size_t J = 0; J < LaneBytes; ++J) {
1466  // Lower undefs (represented by -1 in mask) to zero
1467  uint64_t ByteIndex = M == -1 ? 0 : (uint64_t)M * LaneBytes + J;
1468  Ops[OpIdx++] = DAG.getConstant(ByteIndex, DL, MVT::i32);
1469  }
1470  }
1471 
1472  return DAG.getNode(WebAssemblyISD::SHUFFLE, DL, Op.getValueType(), Ops);
1473 }
1474 
1475 SDValue
1476 WebAssemblyTargetLowering::LowerAccessVectorElement(SDValue Op,
1477  SelectionDAG &DAG) const {
1478  // Allow constant lane indices, expand variable lane indices
1479  SDNode *IdxNode = Op.getOperand(Op.getNumOperands() - 1).getNode();
1480  if (isa<ConstantSDNode>(IdxNode) || IdxNode->isUndef())
1481  return Op;
1482  else
1483  // Perform default expansion
1484  return SDValue();
1485 }
1486 
1489  // 32-bit and 64-bit unrolled shifts will have proper semantics
1490  if (LaneT.bitsGE(MVT::i32))
1491  return DAG.UnrollVectorOp(Op.getNode());
1492  // Otherwise mask the shift value to get proper semantics from 32-bit shift
1493  SDLoc DL(Op);
1494  SDValue ShiftVal = Op.getOperand(1);
1495  uint64_t MaskVal = LaneT.getSizeInBits() - 1;
1496  SDValue MaskedShiftVal = DAG.getNode(
1497  ISD::AND, // mask opcode
1498  DL, ShiftVal.getValueType(), // masked value type
1499  ShiftVal, // original shift value operand
1500  DAG.getConstant(MaskVal, DL, ShiftVal.getValueType()) // mask operand
1501  );
1502 
1503  return DAG.UnrollVectorOp(
1504  DAG.getNode(Op.getOpcode(), // original shift opcode
1505  DL, Op.getValueType(), // original return type
1506  Op.getOperand(0), // original vector operand,
1507  MaskedShiftVal // new masked shift value operand
1508  )
1509  .getNode());
1510 }
1511 
1512 SDValue WebAssemblyTargetLowering::LowerShift(SDValue Op,
1513  SelectionDAG &DAG) const {
1514  SDLoc DL(Op);
1515 
1516  // Only manually lower vector shifts
1518 
1519  // Unroll non-splat vector shifts
1520  BuildVectorSDNode *ShiftVec;
1521  SDValue SplatVal;
1522  if (!(ShiftVec = dyn_cast<BuildVectorSDNode>(Op.getOperand(1).getNode())) ||
1523  !(SplatVal = ShiftVec->getSplatValue()))
1524  return unrollVectorShift(Op, DAG);
1525 
1526  // All splats except i64x2 const splats are handled by patterns
1527  auto *SplatConst = dyn_cast<ConstantSDNode>(SplatVal);
1528  if (!SplatConst || Op.getSimpleValueType() != MVT::v2i64)
1529  return Op;
1530 
1531  // i64x2 const splats are custom lowered to avoid unnecessary wraps
1532  unsigned Opcode;
1533  switch (Op.getOpcode()) {
1534  case ISD::SHL:
1535  Opcode = WebAssemblyISD::VEC_SHL;
1536  break;
1537  case ISD::SRA:
1538  Opcode = WebAssemblyISD::VEC_SHR_S;
1539  break;
1540  case ISD::SRL:
1541  Opcode = WebAssemblyISD::VEC_SHR_U;
1542  break;
1543  default:
1544  llvm_unreachable("unexpected opcode");
1545  }
1546  APInt Shift = SplatConst->getAPIntValue().zextOrTrunc(32);
1547  return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(0),
1548  DAG.getConstant(Shift, DL, MVT::i32));
1549 }
1550 
1551 //===----------------------------------------------------------------------===//
1552 // WebAssembly Optimization Hooks
1553 //===----------------------------------------------------------------------===//
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:598
This file defines the interfaces that WebAssembly uses to lower LLVM code into a selection DAG...
bool isOSEmscripten() const
Tests whether the OS is Emscripten.
Definition: Triple.h:606
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:111
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:169
bool isUndef() const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
const GlobalValue * getGlobal() const
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.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
BR_CC - Conditional branch.
Definition: ISDOpcodes.h:686
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...
static MVT getVectorVT(MVT VT, unsigned NumElements)
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0...
Definition: ISDOpcodes.h:641
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition: ISDOpcodes.h:399
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
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:384
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:738
This class represents a function call, abstracting a target machine&#39;s calling convention.
unsigned Reg
SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition: ValueTypes.h:252
SDValue getBasicBlock(MachineBasicBlock *MBB)
unsigned getVectorNumElements() const
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...
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:930
an instruction that atomically reads a memory location, combines it with another value, and then stores the result back.
Definition: Instructions.h:699
SDNode * getNode() const
get the SDNode which holds the desired result
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.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
void computeSignatureVTs(const FunctionType *Ty, const Function &F, const TargetMachine &TM, SmallVectorImpl< MVT > &Params, SmallVectorImpl< MVT > &Results)
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition: ISDOpcodes.h:474
SDValue getMCSymbol(MCSymbol *Sym, EVT VT)
Register getFrameRegister(const MachineFunction &MF) const override
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
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:1241
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:495
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:168
#define INT64_MIN
Definition: DataTypes.h:80
Shift and rotation operations.
Definition: ISDOpcodes.h:449
Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
Definition: ValueTypes.cpp:264
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:758
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
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
Definition: SelectionDAG.h:652
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:410
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
Definition: SelectionDAG.h:477
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:417
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
This class is used to represent EVT&#39;s, which are used to parameterize some operations.
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...
static mvt_range integer_fixedlen_vector_valuetypes()
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:734
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:414
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
SDValue getTargetFrameIndex(int FI, EVT VT)
Definition: SelectionDAG.h:647
const TargetMachine & getTarget() const
Definition: SelectionDAG.h:418
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition: ISDOpcodes.h:468
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:144
unsigned getTargetFlags() const
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
Definition: SelectionDAG.h:878
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
Definition: SelectionDAG.h:596
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:767
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl) const
Returns a pair of (return value, chain).
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 "...".
Calling convention for emscripten __invoke_* functions.
Definition: CallingConv.h:236
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a vector with the specified, possibly variable...
Definition: ISDOpcodes.h:359
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.
C - The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
Definition: ValueTypes.h:234
Type * getReturnType() const
Returns the type of the ret val.
Definition: Function.h:168
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition: ISDOpcodes.h:165
MVT getSimpleValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the MVT corresponding to this LLVM type. See getValueType.
Control flow instructions. These all have token chains.
Definition: ISDOpcodes.h:665
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:46
const Triple & getTargetTriple() const
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.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE...
Definition: ISDOpcodes.h:767
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:364
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.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
Fast - This calling convention attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:42
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:806
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
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:758
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:1193
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:205
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:672
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.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:40
unsigned first
WebAssemblyTargetLowering(const TargetMachine &TM, const WebAssemblySubtarget &STI)
SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type...
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
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:420
Iterator for intrusive lists based on ilist_node.
CCState - This class holds information needed while lowering arguments and return values...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
Definition: SelectionDAG.h:642
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:390
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition: ISDOpcodes.h:371
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition: ValueTypes.h:264
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:837
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
Definition: SelectionDAG.h:750
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:452
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
Definition: ISDOpcodes.h:613
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:716
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, SDValue N)
Definition: SelectionDAG.h:695
const Function & getFunction() const
Return the LLVM function that this machine code represents.
static mvt_range integer_valuetypes()
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:940
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:163
EVT getMemoryVT() const
Return the type of the in-memory value.
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:459
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition: ISDOpcodes.h:344
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
Flags
Flags values. These may be or&#39;d together.
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:674
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:763
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:215
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:426
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:721
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:525
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.
#define I(x, y, z)
Definition: MD5.cpp:58
#define N
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
This file declares WebAssembly-specific per-machine-function information.
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:279
static CCValAssign getMem(unsigned ValNo, MVT ValVT, unsigned Offset, MVT LocVT, LocInfo HTP)
unsigned getOpcode() const
FSINCOS - Compute both fsin and fcos as a single operation.
Definition: ISDOpcodes.h:644
SDValue getValue(unsigned R) const
void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
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)
int CreateStackObject(uint64_t Size, Align 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...
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:575
LLVM Value Representation.
Definition: Value.h:74
void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty, SmallVectorImpl< MVT > &ValueVTs)
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
FMA - Perform a * b + c with no intermediate rounding step.
Definition: ISDOpcodes.h:334
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
static mvt_range fixedlen_vector_valuetypes()
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
const WebAssemblyInstrInfo * getInstrInfo() const override
unsigned getNumOperands() const
Register getReg() const
getReg - Returns the register number.
const SDValue & getOperand(unsigned i) const
bool verifyReturnAddressArgumentIsConstant(SDValue Op, SelectionDAG &DAG) 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:415
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
#define _
LLVMContext * getContext() const
Definition: SelectionDAG.h:424
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition: ISDOpcodes.h:419
BRIND - Indirect branch.
Definition: ISDOpcodes.h:670
This class is used to represent ISD::LOAD nodes.
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary...
Definition: ISDOpcodes.h:659