LLVM  12.0.0git
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 "WebAssemblyUtilities.h"
20 #include "llvm/CodeGen/Analysis.h"
28 #include "llvm/IR/DiagnosticInfo.h"
30 #include "llvm/IR/Function.h"
31 #include "llvm/IR/Intrinsics.h"
32 #include "llvm/IR/IntrinsicsWebAssembly.h"
33 #include "llvm/Support/Debug.h"
38 using namespace llvm;
39 
40 #define DEBUG_TYPE "wasm-lower"
41 
43  const TargetMachine &TM, const WebAssemblySubtarget &STI)
44  : TargetLowering(TM), Subtarget(&STI) {
45  auto MVTPtr = Subtarget->hasAddr64() ? MVT::i64 : MVT::i32;
46 
47  // Booleans always contain 0 or 1.
49  // Except in SIMD vectors
51  // We don't know the microarchitecture here, so just reduce register pressure.
53  // Tell ISel that we have a stack pointer.
55  Subtarget->hasAddr64() ? WebAssembly::SP64 : WebAssembly::SP32);
56  // Set up the register classes.
57  addRegisterClass(MVT::i32, &WebAssembly::I32RegClass);
58  addRegisterClass(MVT::i64, &WebAssembly::I64RegClass);
59  addRegisterClass(MVT::f32, &WebAssembly::F32RegClass);
60  addRegisterClass(MVT::f64, &WebAssembly::F64RegClass);
61  if (Subtarget->hasSIMD128()) {
62  addRegisterClass(MVT::v16i8, &WebAssembly::V128RegClass);
63  addRegisterClass(MVT::v8i16, &WebAssembly::V128RegClass);
64  addRegisterClass(MVT::v4i32, &WebAssembly::V128RegClass);
65  addRegisterClass(MVT::v4f32, &WebAssembly::V128RegClass);
66  addRegisterClass(MVT::v2i64, &WebAssembly::V128RegClass);
67  addRegisterClass(MVT::v2f64, &WebAssembly::V128RegClass);
68  }
69  // Compute derived properties from the register classes.
71 
78 
79  // Take the default expansion for va_arg, va_copy, and va_end. There is no
80  // default action for va_start, so we do that custom.
85 
86  for (auto T : {MVT::f32, MVT::f64, MVT::v4f32, MVT::v2f64}) {
87  // Don't expand the floating-point types to constant pools.
89  // Expand floating-point comparisons.
90  for (auto CC : {ISD::SETO, ISD::SETUO, ISD::SETUEQ, ISD::SETONE,
93  // Expand floating-point library function operators.
94  for (auto Op :
97  // Note supported floating-point library function operators that otherwise
98  // default to expand.
99  for (auto Op :
102  // Support minimum and maximum, which otherwise default to expand.
105  // WebAssembly currently has no builtin f16 support.
110  }
111 
112  // Expand unavailable integer operations.
113  for (auto Op :
117  for (auto T : {MVT::i32, MVT::i64})
119  if (Subtarget->hasSIMD128())
120  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64})
122  }
123 
124  // SIMD-specific configuration
125  if (Subtarget->hasSIMD128()) {
126  // Hoist bitcasts out of shuffles
128 
129  // Combine extends of extract_subvectors into widening ops
132 
133  // Support saturating add for i8x16 and i16x8
134  for (auto Op : {ISD::SADDSAT, ISD::UADDSAT})
135  for (auto T : {MVT::v16i8, MVT::v8i16})
137 
138  // Support integer abs
139  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
141 
142  // Custom lower BUILD_VECTORs to minimize number of replace_lanes
144  MVT::v2f64})
146 
147  // We have custom shuffle lowering to expose the shuffle mask
149  MVT::v2f64})
151 
152  // Custom lowering since wasm shifts must have a scalar shift amount
153  for (auto Op : {ISD::SHL, ISD::SRA, ISD::SRL})
154  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64})
156 
157  // Custom lower lane accesses to expand out variable indices
160  MVT::v2f64})
162 
163  // There is no i8x16.mul instruction
165 
166  // There is no vector conditional select instruction
168  MVT::v2f64})
170 
171  // Expand integer operations supported for scalars but not SIMD
174  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64})
176 
177  // But we do have integer min and max operations
178  for (auto Op : {ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX})
179  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
181 
182  // Expand float operations supported for scalars but not SIMD
186  for (auto T : {MVT::v4f32, MVT::v2f64})
188 
189  // Expand operations not supported for i64x2 vectors
190  for (unsigned CC = 0; CC < ISD::SETCC_INVALID; ++CC)
191  setCondCodeAction(static_cast<ISD::CondCode>(CC), MVT::v2i64, Custom);
192 
193  // 64x2 conversions are not in the spec
194  for (auto Op :
196  for (auto T : {MVT::v2i64, MVT::v2f64})
198  }
199 
200  // As a special case, these operators use the type to mean the type to
201  // sign-extend from.
203  if (!Subtarget->hasSignExt()) {
204  // Sign extends are legal only when extending a vector extract
205  auto Action = Subtarget->hasSIMD128() ? Custom : Expand;
206  for (auto T : {MVT::i8, MVT::i16, MVT::i32})
208  }
211 
212  // Dynamic stack allocation: use the default expansion.
216 
220 
221  // Expand these forms; we pattern-match the forms that we can handle in isel.
222  for (auto T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
223  for (auto Op : {ISD::BR_CC, ISD::SELECT_CC})
225 
226  // We have custom switch handling.
228 
229  // WebAssembly doesn't have:
230  // - Floating-point extending loads.
231  // - Floating-point truncating stores.
232  // - i1 extending loads.
233  // - truncating SIMD stores and most extending loads
236  for (auto T : MVT::integer_valuetypes())
239  if (Subtarget->hasSIMD128()) {
241  MVT::v2f64}) {
242  for (auto MemT : MVT::fixedlen_vector_valuetypes()) {
243  if (MVT(T) != MemT) {
244  setTruncStoreAction(T, MemT, Expand);
246  setLoadExtAction(Ext, T, MemT, Expand);
247  }
248  }
249  }
250  // But some vector extending loads are legal
251  for (auto Ext : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}) {
255  }
256  // And some truncating stores are legal as well
259  }
260 
261  // Don't do anything clever with build_pairs
263 
264  // Trap lowers to wasm unreachable
267 
268  // Exception handling intrinsics
272 
274 
275  // Override the __gnu_f2h_ieee/__gnu_h2f_ieee names so that the f32 name is
276  // consistent with the f64 and f128 names.
277  setLibcallName(RTLIB::FPEXT_F16_F32, "__extendhfsf2");
278  setLibcallName(RTLIB::FPROUND_F32_F16, "__truncsfhf2");
279 
280  // Define the emscripten name for return address helper.
281  // TODO: when implementing other Wasm backends, make this generic or only do
282  // this on emscripten depending on what they end up doing.
283  setLibcallName(RTLIB::RETURN_ADDRESS, "emscripten_return_address");
284 
285  // Always convert switches to br_tables unless there is only one case, which
286  // is equivalent to a simple branch. This reduces code size for wasm, and we
287  // defer possible jump table optimizations to the VM.
289 }
290 
292 WebAssemblyTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
293  // We have wasm instructions for these
294  switch (AI->getOperation()) {
295  case AtomicRMWInst::Add:
296  case AtomicRMWInst::Sub:
297  case AtomicRMWInst::And:
298  case AtomicRMWInst::Or:
299  case AtomicRMWInst::Xor:
300  case AtomicRMWInst::Xchg:
302  default:
303  break;
304  }
306 }
307 
308 FastISel *WebAssemblyTargetLowering::createFastISel(
309  FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo) const {
310  return WebAssembly::createFastISel(FuncInfo, LibInfo);
311 }
312 
313 MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
314  EVT VT) const {
315  unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1);
316  if (BitWidth > 1 && BitWidth < 8)
317  BitWidth = 8;
318 
319  if (BitWidth > 64) {
320  // The shift will be lowered to a libcall, and compiler-rt libcalls expect
321  // the count to be an i32.
322  BitWidth = 32;
324  "32-bit shift counts ought to be enough for anyone");
325  }
326 
329  "Unable to represent scalar shift amount type");
330  return Result;
331 }
332 
333 // Lower an fp-to-int conversion operator from the LLVM opcode, which has an
334 // undefined result on invalid/overflow, to the WebAssembly opcode, which
335 // traps on invalid/overflow.
337  MachineBasicBlock *BB,
338  const TargetInstrInfo &TII,
339  bool IsUnsigned, bool Int64,
340  bool Float64, unsigned LoweredOpcode) {
342 
343  Register OutReg = MI.getOperand(0).getReg();
344  Register InReg = MI.getOperand(1).getReg();
345 
346  unsigned Abs = Float64 ? WebAssembly::ABS_F64 : WebAssembly::ABS_F32;
347  unsigned FConst = Float64 ? WebAssembly::CONST_F64 : WebAssembly::CONST_F32;
348  unsigned LT = Float64 ? WebAssembly::LT_F64 : WebAssembly::LT_F32;
349  unsigned GE = Float64 ? WebAssembly::GE_F64 : WebAssembly::GE_F32;
350  unsigned IConst = Int64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32;
351  unsigned Eqz = WebAssembly::EQZ_I32;
352  unsigned And = WebAssembly::AND_I32;
353  int64_t Limit = Int64 ? INT64_MIN : INT32_MIN;
354  int64_t Substitute = IsUnsigned ? 0 : Limit;
355  double CmpVal = IsUnsigned ? -(double)Limit * 2.0 : -(double)Limit;
356  auto &Context = BB->getParent()->getFunction().getContext();
358 
359  const BasicBlock *LLVMBB = BB->getBasicBlock();
360  MachineFunction *F = BB->getParent();
361  MachineBasicBlock *TrueMBB = F->CreateMachineBasicBlock(LLVMBB);
362  MachineBasicBlock *FalseMBB = F->CreateMachineBasicBlock(LLVMBB);
363  MachineBasicBlock *DoneMBB = F->CreateMachineBasicBlock(LLVMBB);
364 
366  F->insert(It, FalseMBB);
367  F->insert(It, TrueMBB);
368  F->insert(It, DoneMBB);
369 
370  // Transfer the remainder of BB and its successor edges to DoneMBB.
371  DoneMBB->splice(DoneMBB->begin(), BB, std::next(MI.getIterator()), BB->end());
372  DoneMBB->transferSuccessorsAndUpdatePHIs(BB);
373 
374  BB->addSuccessor(TrueMBB);
375  BB->addSuccessor(FalseMBB);
376  TrueMBB->addSuccessor(DoneMBB);
377  FalseMBB->addSuccessor(DoneMBB);
378 
379  unsigned Tmp0, Tmp1, CmpReg, EqzReg, FalseReg, TrueReg;
380  Tmp0 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
381  Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
382  CmpReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
383  EqzReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
384  FalseReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
385  TrueReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
386 
387  MI.eraseFromParent();
388  // For signed numbers, we can do a single comparison to determine whether
389  // fabs(x) is within range.
390  if (IsUnsigned) {
391  Tmp0 = InReg;
392  } else {
393  BuildMI(BB, DL, TII.get(Abs), Tmp0).addReg(InReg);
394  }
395  BuildMI(BB, DL, TII.get(FConst), Tmp1)
396  .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, CmpVal)));
397  BuildMI(BB, DL, TII.get(LT), CmpReg).addReg(Tmp0).addReg(Tmp1);
398 
399  // For unsigned numbers, we have to do a separate comparison with zero.
400  if (IsUnsigned) {
401  Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
402  Register SecondCmpReg =
403  MRI.createVirtualRegister(&WebAssembly::I32RegClass);
404  Register AndReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
405  BuildMI(BB, DL, TII.get(FConst), Tmp1)
406  .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, 0.0)));
407  BuildMI(BB, DL, TII.get(GE), SecondCmpReg).addReg(Tmp0).addReg(Tmp1);
408  BuildMI(BB, DL, TII.get(And), AndReg).addReg(CmpReg).addReg(SecondCmpReg);
409  CmpReg = AndReg;
410  }
411 
412  BuildMI(BB, DL, TII.get(Eqz), EqzReg).addReg(CmpReg);
413 
414  // Create the CFG diamond to select between doing the conversion or using
415  // the substitute value.
416  BuildMI(BB, DL, TII.get(WebAssembly::BR_IF)).addMBB(TrueMBB).addReg(EqzReg);
417  BuildMI(FalseMBB, DL, TII.get(LoweredOpcode), FalseReg).addReg(InReg);
418  BuildMI(FalseMBB, DL, TII.get(WebAssembly::BR)).addMBB(DoneMBB);
419  BuildMI(TrueMBB, DL, TII.get(IConst), TrueReg).addImm(Substitute);
420  BuildMI(*DoneMBB, DoneMBB->begin(), DL, TII.get(TargetOpcode::PHI), OutReg)
421  .addReg(FalseReg)
422  .addMBB(FalseMBB)
423  .addReg(TrueReg)
424  .addMBB(TrueMBB);
425 
426  return DoneMBB;
427 }
428 
431  const TargetInstrInfo &TII) {
432  MachineInstr &CallParams = *CallResults.getPrevNode();
433  assert(CallParams.getOpcode() == WebAssembly::CALL_PARAMS);
434  assert(CallResults.getOpcode() == WebAssembly::CALL_RESULTS ||
435  CallResults.getOpcode() == WebAssembly::RET_CALL_RESULTS);
436 
437  bool IsIndirect = CallParams.getOperand(0).isReg();
438  bool IsRetCall = CallResults.getOpcode() == WebAssembly::RET_CALL_RESULTS;
439 
440  unsigned CallOp;
441  if (IsIndirect && IsRetCall) {
442  CallOp = WebAssembly::RET_CALL_INDIRECT;
443  } else if (IsIndirect) {
444  CallOp = WebAssembly::CALL_INDIRECT;
445  } else if (IsRetCall) {
446  CallOp = WebAssembly::RET_CALL;
447  } else {
448  CallOp = WebAssembly::CALL;
449  }
450 
451  MachineFunction &MF = *BB->getParent();
452  const MCInstrDesc &MCID = TII.get(CallOp);
453  MachineInstrBuilder MIB(MF, MF.CreateMachineInstr(MCID, DL));
454 
455  // See if we must truncate the function pointer.
456  // CALL_INDIRECT takes an i32, but in wasm64 we represent function pointers
457  // as 64-bit for uniformity with other pointer types.
458  if (IsIndirect && MF.getSubtarget<WebAssemblySubtarget>().hasAddr64()) {
459  Register Reg32 =
460  MF.getRegInfo().createVirtualRegister(&WebAssembly::I32RegClass);
461  auto &FnPtr = CallParams.getOperand(0);
462  BuildMI(*BB, CallResults.getIterator(), DL,
463  TII.get(WebAssembly::I32_WRAP_I64), Reg32)
464  .addReg(FnPtr.getReg());
465  FnPtr.setReg(Reg32);
466  }
467 
468  // Move the function pointer to the end of the arguments for indirect calls
469  if (IsIndirect) {
470  auto FnPtr = CallParams.getOperand(0);
471  CallParams.RemoveOperand(0);
472  CallParams.addOperand(FnPtr);
473  }
474 
475  for (auto Def : CallResults.defs())
476  MIB.add(Def);
477 
478  // Add placeholders for the type index and immediate flags
479  if (IsIndirect) {
480  MIB.addImm(0);
481  MIB.addImm(0);
482 
483  // Ensure that the object file has a __indirect_function_table import, as we
484  // call_indirect against it.
486  MF.getContext(), "__indirect_function_table");
487  // Until call_indirect emits TABLE_NUMBER relocs against this symbol, mark
488  // it as NO_STRIP so as to ensure that the indirect function table makes it
489  // to linked output.
490  Sym->setNoStrip();
491  }
492 
493  for (auto Use : CallParams.uses())
494  MIB.add(Use);
495 
496  BB->insert(CallResults.getIterator(), MIB);
497  CallParams.eraseFromParent();
498  CallResults.eraseFromParent();
499 
500  return BB;
501 }
502 
503 MachineBasicBlock *WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
504  MachineInstr &MI, MachineBasicBlock *BB) const {
505  const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
506  DebugLoc DL = MI.getDebugLoc();
507 
508  switch (MI.getOpcode()) {
509  default:
510  llvm_unreachable("Unexpected instr type to insert");
511  case WebAssembly::FP_TO_SINT_I32_F32:
512  return LowerFPToInt(MI, DL, BB, TII, false, false, false,
513  WebAssembly::I32_TRUNC_S_F32);
514  case WebAssembly::FP_TO_UINT_I32_F32:
515  return LowerFPToInt(MI, DL, BB, TII, true, false, false,
516  WebAssembly::I32_TRUNC_U_F32);
517  case WebAssembly::FP_TO_SINT_I64_F32:
518  return LowerFPToInt(MI, DL, BB, TII, false, true, false,
519  WebAssembly::I64_TRUNC_S_F32);
520  case WebAssembly::FP_TO_UINT_I64_F32:
521  return LowerFPToInt(MI, DL, BB, TII, true, true, false,
522  WebAssembly::I64_TRUNC_U_F32);
523  case WebAssembly::FP_TO_SINT_I32_F64:
524  return LowerFPToInt(MI, DL, BB, TII, false, false, true,
525  WebAssembly::I32_TRUNC_S_F64);
526  case WebAssembly::FP_TO_UINT_I32_F64:
527  return LowerFPToInt(MI, DL, BB, TII, true, false, true,
528  WebAssembly::I32_TRUNC_U_F64);
529  case WebAssembly::FP_TO_SINT_I64_F64:
530  return LowerFPToInt(MI, DL, BB, TII, false, true, true,
531  WebAssembly::I64_TRUNC_S_F64);
532  case WebAssembly::FP_TO_UINT_I64_F64:
533  return LowerFPToInt(MI, DL, BB, TII, true, true, true,
534  WebAssembly::I64_TRUNC_U_F64);
535  case WebAssembly::CALL_RESULTS:
536  case WebAssembly::RET_CALL_RESULTS:
537  return LowerCallResults(MI, DL, BB, TII);
538  }
539 }
540 
541 const char *
542 WebAssemblyTargetLowering::getTargetNodeName(unsigned Opcode) const {
543  switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) {
546  break;
547 #define HANDLE_NODETYPE(NODE) \
548  case WebAssemblyISD::NODE: \
549  return "WebAssemblyISD::" #NODE;
550 #define HANDLE_MEM_NODETYPE(NODE) HANDLE_NODETYPE(NODE)
551 #include "WebAssemblyISD.def"
552 #undef HANDLE_MEM_NODETYPE
553 #undef HANDLE_NODETYPE
554  }
555  return nullptr;
556 }
557 
558 std::pair<unsigned, const TargetRegisterClass *>
559 WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
560  const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
561  // First, see if this is a constraint that directly corresponds to a
562  // WebAssembly register class.
563  if (Constraint.size() == 1) {
564  switch (Constraint[0]) {
565  case 'r':
566  assert(VT != MVT::iPTR && "Pointer MVT not expected here");
567  if (Subtarget->hasSIMD128() && VT.isVector()) {
568  if (VT.getSizeInBits() == 128)
569  return std::make_pair(0U, &WebAssembly::V128RegClass);
570  }
571  if (VT.isInteger() && !VT.isVector()) {
572  if (VT.getSizeInBits() <= 32)
573  return std::make_pair(0U, &WebAssembly::I32RegClass);
574  if (VT.getSizeInBits() <= 64)
575  return std::make_pair(0U, &WebAssembly::I64RegClass);
576  }
577  if (VT.isFloatingPoint() && !VT.isVector()) {
578  switch (VT.getSizeInBits()) {
579  case 32:
580  return std::make_pair(0U, &WebAssembly::F32RegClass);
581  case 64:
582  return std::make_pair(0U, &WebAssembly::F64RegClass);
583  default:
584  break;
585  }
586  }
587  break;
588  default:
589  break;
590  }
591  }
592 
593  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
594 }
595 
596 bool WebAssemblyTargetLowering::isCheapToSpeculateCttz() const {
597  // Assume ctz is a relatively cheap operation.
598  return true;
599 }
600 
601 bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz() const {
602  // Assume clz is a relatively cheap operation.
603  return true;
604 }
605 
606 bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
607  const AddrMode &AM,
608  Type *Ty, unsigned AS,
609  Instruction *I) const {
610  // WebAssembly offsets are added as unsigned without wrapping. The
611  // isLegalAddressingMode gives us no way to determine if wrapping could be
612  // happening, so we approximate this by accepting only non-negative offsets.
613  if (AM.BaseOffs < 0)
614  return false;
615 
616  // WebAssembly has no scale register operands.
617  if (AM.Scale != 0)
618  return false;
619 
620  // Everything else is legal.
621  return true;
622 }
623 
624 bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses(
625  EVT /*VT*/, unsigned /*AddrSpace*/, unsigned /*Align*/,
626  MachineMemOperand::Flags /*Flags*/, bool *Fast) const {
627  // WebAssembly supports unaligned accesses, though it should be declared
628  // with the p2align attribute on loads and stores which do so, and there
629  // may be a performance impact. We tell LLVM they're "fast" because
630  // for the kinds of things that LLVM uses this for (merging adjacent stores
631  // of constants, etc.), WebAssembly implementations will either want the
632  // unaligned access or they'll split anyway.
633  if (Fast)
634  *Fast = true;
635  return true;
636 }
637 
638 bool WebAssemblyTargetLowering::isIntDivCheap(EVT VT,
639  AttributeList Attr) const {
640  // The current thinking is that wasm engines will perform this optimization,
641  // so we can save on code size.
642  return true;
643 }
644 
645 bool WebAssemblyTargetLowering::isVectorLoadExtDesirable(SDValue ExtVal) const {
646  EVT ExtT = ExtVal.getValueType();
647  EVT MemT = cast<LoadSDNode>(ExtVal->getOperand(0))->getValueType(0);
648  return (ExtT == MVT::v8i16 && MemT == MVT::v8i8) ||
649  (ExtT == MVT::v4i32 && MemT == MVT::v4i16) ||
650  (ExtT == MVT::v2i64 && MemT == MVT::v2i32);
651 }
652 
653 EVT WebAssemblyTargetLowering::getSetCCResultType(const DataLayout &DL,
654  LLVMContext &C,
655  EVT VT) const {
656  if (VT.isVector())
658 
659  // So far, all branch instructions in Wasm take an I32 condition.
660  // The default TargetLowering::getSetCCResultType returns the pointer size,
661  // which would be useful to reduce instruction counts when testing
662  // against 64-bit pointers/values if at some point Wasm supports that.
663  return EVT::getIntegerVT(C, 32);
664 }
665 
666 bool WebAssemblyTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
667  const CallInst &I,
668  MachineFunction &MF,
669  unsigned Intrinsic) const {
670  switch (Intrinsic) {
671  case Intrinsic::wasm_memory_atomic_notify:
673  Info.memVT = MVT::i32;
674  Info.ptrVal = I.getArgOperand(0);
675  Info.offset = 0;
676  Info.align = Align(4);
677  // atomic.notify instruction does not really load the memory specified with
678  // this argument, but MachineMemOperand should either be load or store, so
679  // we set this to a load.
680  // FIXME Volatile isn't really correct, but currently all LLVM atomic
681  // instructions are treated as volatiles in the backend, so we should be
682  // consistent. The same applies for wasm_atomic_wait intrinsics too.
684  return true;
685  case Intrinsic::wasm_memory_atomic_wait32:
687  Info.memVT = MVT::i32;
688  Info.ptrVal = I.getArgOperand(0);
689  Info.offset = 0;
690  Info.align = Align(4);
692  return true;
693  case Intrinsic::wasm_memory_atomic_wait64:
695  Info.memVT = MVT::i64;
696  Info.ptrVal = I.getArgOperand(0);
697  Info.offset = 0;
698  Info.align = Align(8);
700  return true;
701  case Intrinsic::wasm_load32_zero:
702  case Intrinsic::wasm_load64_zero:
704  Info.memVT = Intrinsic == Intrinsic::wasm_load32_zero ? MVT::i32 : MVT::i64;
705  Info.ptrVal = I.getArgOperand(0);
706  Info.offset = 0;
707  Info.align = Info.memVT == MVT::i32 ? Align(4) : Align(8);
709  return true;
710  case Intrinsic::wasm_load8_lane:
711  case Intrinsic::wasm_load16_lane:
712  case Intrinsic::wasm_load32_lane:
713  case Intrinsic::wasm_load64_lane:
714  case Intrinsic::wasm_store8_lane:
715  case Intrinsic::wasm_store16_lane:
716  case Intrinsic::wasm_store32_lane:
717  case Intrinsic::wasm_store64_lane: {
718  MVT MemVT;
719  Align MemAlign;
720  switch (Intrinsic) {
721  case Intrinsic::wasm_load8_lane:
722  case Intrinsic::wasm_store8_lane:
723  MemVT = MVT::i8;
724  MemAlign = Align(1);
725  break;
726  case Intrinsic::wasm_load16_lane:
727  case Intrinsic::wasm_store16_lane:
728  MemVT = MVT::i16;
729  MemAlign = Align(2);
730  break;
731  case Intrinsic::wasm_load32_lane:
732  case Intrinsic::wasm_store32_lane:
733  MemVT = MVT::i32;
734  MemAlign = Align(4);
735  break;
736  case Intrinsic::wasm_load64_lane:
737  case Intrinsic::wasm_store64_lane:
738  MemVT = MVT::i64;
739  MemAlign = Align(8);
740  break;
741  default:
742  llvm_unreachable("unexpected intrinsic");
743  }
744  if (Intrinsic == Intrinsic::wasm_load8_lane ||
745  Intrinsic == Intrinsic::wasm_load16_lane ||
746  Intrinsic == Intrinsic::wasm_load32_lane ||
747  Intrinsic == Intrinsic::wasm_load64_lane) {
750  } else {
753  }
754  Info.ptrVal = I.getArgOperand(0);
755  Info.memVT = MemVT;
756  Info.offset = 0;
757  Info.align = MemAlign;
758  return true;
759  }
760  case Intrinsic::wasm_prefetch_t:
761  case Intrinsic::wasm_prefetch_nt: {
763  Info.memVT = MVT::i8;
764  Info.ptrVal = I.getArgOperand(0);
765  Info.offset = 0;
766  Info.align = Align(1);
768  return true;
769  }
770  default:
771  return false;
772  }
773 }
774 
775 //===----------------------------------------------------------------------===//
776 // WebAssembly Lowering private implementation.
777 //===----------------------------------------------------------------------===//
778 
779 //===----------------------------------------------------------------------===//
780 // Lowering Code
781 //===----------------------------------------------------------------------===//
782 
783 static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *Msg) {
785  DAG.getContext()->diagnose(
786  DiagnosticInfoUnsupported(MF.getFunction(), Msg, DL.getDebugLoc()));
787 }
788 
789 // Test whether the given calling convention is supported.
790 static bool callingConvSupported(CallingConv::ID CallConv) {
791  // We currently support the language-independent target-independent
792  // conventions. We don't yet have a way to annotate calls with properties like
793  // "cold", and we don't have any call-clobbered registers, so these are mostly
794  // all handled the same.
795  return CallConv == CallingConv::C || CallConv == CallingConv::Fast ||
796  CallConv == CallingConv::Cold ||
797  CallConv == CallingConv::PreserveMost ||
798  CallConv == CallingConv::PreserveAll ||
799  CallConv == CallingConv::CXX_FAST_TLS ||
801  CallConv == CallingConv::Swift;
802 }
803 
804 SDValue
805 WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
806  SmallVectorImpl<SDValue> &InVals) const {
807  SelectionDAG &DAG = CLI.DAG;
808  SDLoc DL = CLI.DL;
809  SDValue Chain = CLI.Chain;
810  SDValue Callee = CLI.Callee;
812  auto Layout = MF.getDataLayout();
813 
814  CallingConv::ID CallConv = CLI.CallConv;
815  if (!callingConvSupported(CallConv))
816  fail(DL, DAG,
817  "WebAssembly doesn't support language-specific or target-specific "
818  "calling conventions yet");
819  if (CLI.IsPatchPoint)
820  fail(DL, DAG, "WebAssembly doesn't support patch point yet");
821 
822  if (CLI.IsTailCall) {
823  auto NoTail = [&](const char *Msg) {
824  if (CLI.CB && CLI.CB->isMustTailCall())
825  fail(DL, DAG, Msg);
826  CLI.IsTailCall = false;
827  };
828 
829  if (!Subtarget->hasTailCall())
830  NoTail("WebAssembly 'tail-call' feature not enabled");
831 
832  // Varargs calls cannot be tail calls because the buffer is on the stack
833  if (CLI.IsVarArg)
834  NoTail("WebAssembly does not support varargs tail calls");
835 
836  // Do not tail call unless caller and callee return types match
837  const Function &F = MF.getFunction();
838  const TargetMachine &TM = getTargetMachine();
839  Type *RetTy = F.getReturnType();
840  SmallVector<MVT, 4> CallerRetTys;
841  SmallVector<MVT, 4> CalleeRetTys;
842  computeLegalValueVTs(F, TM, RetTy, CallerRetTys);
843  computeLegalValueVTs(F, TM, CLI.RetTy, CalleeRetTys);
844  bool TypesMatch = CallerRetTys.size() == CalleeRetTys.size() &&
845  std::equal(CallerRetTys.begin(), CallerRetTys.end(),
846  CalleeRetTys.begin());
847  if (!TypesMatch)
848  NoTail("WebAssembly tail call requires caller and callee return types to "
849  "match");
850 
851  // If pointers to local stack values are passed, we cannot tail call
852  if (CLI.CB) {
853  for (auto &Arg : CLI.CB->args()) {
854  Value *Val = Arg.get();
855  // Trace the value back through pointer operations
856  while (true) {
857  Value *Src = Val->stripPointerCastsAndAliases();
858  if (auto *GEP = dyn_cast<GetElementPtrInst>(Src))
859  Src = GEP->getPointerOperand();
860  if (Val == Src)
861  break;
862  Val = Src;
863  }
864  if (isa<AllocaInst>(Val)) {
865  NoTail(
866  "WebAssembly does not support tail calling with stack arguments");
867  break;
868  }
869  }
870  }
871  }
872 
874  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
875  SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
876 
877  // The generic code may have added an sret argument. If we're lowering an
878  // invoke function, the ABI requires that the function pointer be the first
879  // argument, so we may have to swap the arguments.
880  if (CallConv == CallingConv::WASM_EmscriptenInvoke && Outs.size() >= 2 &&
881  Outs[0].Flags.isSRet()) {
882  std::swap(Outs[0], Outs[1]);
883  std::swap(OutVals[0], OutVals[1]);
884  }
885 
886  bool HasSwiftSelfArg = false;
887  bool HasSwiftErrorArg = false;
888  unsigned NumFixedArgs = 0;
889  for (unsigned I = 0; I < Outs.size(); ++I) {
890  const ISD::OutputArg &Out = Outs[I];
891  SDValue &OutVal = OutVals[I];
892  HasSwiftSelfArg |= Out.Flags.isSwiftSelf();
893  HasSwiftErrorArg |= Out.Flags.isSwiftError();
894  if (Out.Flags.isNest())
895  fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
896  if (Out.Flags.isInAlloca())
897  fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
898  if (Out.Flags.isInConsecutiveRegs())
899  fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
900  if (Out.Flags.isInConsecutiveRegsLast())
901  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
902  if (Out.Flags.isByVal() && Out.Flags.getByValSize() != 0) {
903  auto &MFI = MF.getFrameInfo();
904  int FI = MFI.CreateStackObject(Out.Flags.getByValSize(),
906  /*isSS=*/false);
907  SDValue SizeNode =
909  SDValue FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
910  Chain = DAG.getMemcpy(
911  Chain, DL, FINode, OutVal, SizeNode, Out.Flags.getNonZeroByValAlign(),
912  /*isVolatile*/ false, /*AlwaysInline=*/false,
913  /*isTailCall*/ false, MachinePointerInfo(), MachinePointerInfo());
914  OutVal = FINode;
915  }
916  // Count the number of fixed args *after* legalization.
917  NumFixedArgs += Out.IsFixed;
918  }
919 
920  bool IsVarArg = CLI.IsVarArg;
921  auto PtrVT = getPointerTy(Layout);
922 
923  // For swiftcc, emit additional swiftself and swifterror arguments
924  // if there aren't. These additional arguments are also added for callee
925  // signature They are necessary to match callee and caller signature for
926  // indirect call.
927  if (CallConv == CallingConv::Swift) {
928  if (!HasSwiftSelfArg) {
929  NumFixedArgs++;
931  Arg.Flags.setSwiftSelf();
932  CLI.Outs.push_back(Arg);
933  SDValue ArgVal = DAG.getUNDEF(PtrVT);
934  CLI.OutVals.push_back(ArgVal);
935  }
936  if (!HasSwiftErrorArg) {
937  NumFixedArgs++;
939  Arg.Flags.setSwiftError();
940  CLI.Outs.push_back(Arg);
941  SDValue ArgVal = DAG.getUNDEF(PtrVT);
942  CLI.OutVals.push_back(ArgVal);
943  }
944  }
945 
946  // Analyze operands of the call, assigning locations to each operand.
948  CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
949 
950  if (IsVarArg) {
951  // Outgoing non-fixed arguments are placed in a buffer. First
952  // compute their offsets and the total amount of buffer space needed.
953  for (unsigned I = NumFixedArgs; I < Outs.size(); ++I) {
954  const ISD::OutputArg &Out = Outs[I];
955  SDValue &Arg = OutVals[I];
956  EVT VT = Arg.getValueType();
957  assert(VT != MVT::iPTR && "Legalized args should be concrete");
958  Type *Ty = VT.getTypeForEVT(*DAG.getContext());
959  Align Alignment =
960  std::max(Out.Flags.getNonZeroOrigAlign(), Layout.getABITypeAlign(Ty));
961  unsigned Offset =
962  CCInfo.AllocateStack(Layout.getTypeAllocSize(Ty), Alignment);
963  CCInfo.addLoc(CCValAssign::getMem(ArgLocs.size(), VT.getSimpleVT(),
964  Offset, VT.getSimpleVT(),
966  }
967  }
968 
969  unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
970 
971  SDValue FINode;
972  if (IsVarArg && NumBytes) {
973  // For non-fixed arguments, next emit stores to store the argument values
974  // to the stack buffer at the offsets computed above.
975  int FI = MF.getFrameInfo().CreateStackObject(NumBytes,
976  Layout.getStackAlignment(),
977  /*isSS=*/false);
978  unsigned ValNo = 0;
980  for (SDValue Arg : drop_begin(OutVals, NumFixedArgs)) {
981  assert(ArgLocs[ValNo].getValNo() == ValNo &&
982  "ArgLocs should remain in order and only hold varargs args");
983  unsigned Offset = ArgLocs[ValNo++].getLocMemOffset();
984  FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
985  SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, FINode,
986  DAG.getConstant(Offset, DL, PtrVT));
987  Chains.push_back(
988  DAG.getStore(Chain, DL, Arg, Add,
990  }
991  if (!Chains.empty())
992  Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
993  } else if (IsVarArg) {
994  FINode = DAG.getIntPtrConstant(0, DL);
995  }
996 
997  if (Callee->getOpcode() == ISD::GlobalAddress) {
998  // If the callee is a GlobalAddress node (quite common, every direct call
999  // is) turn it into a TargetGlobalAddress node so that LowerGlobalAddress
1000  // doesn't at MO_GOT which is not needed for direct calls.
1001  GlobalAddressSDNode* GA = cast<GlobalAddressSDNode>(Callee);
1003  getPointerTy(DAG.getDataLayout()),
1004  GA->getOffset());
1006  getPointerTy(DAG.getDataLayout()), Callee);
1007  }
1008 
1009  // Compute the operands for the CALLn node.
1011  Ops.push_back(Chain);
1012  Ops.push_back(Callee);
1013 
1014  // Add all fixed arguments. Note that for non-varargs calls, NumFixedArgs
1015  // isn't reliable.
1016  Ops.append(OutVals.begin(),
1017  IsVarArg ? OutVals.begin() + NumFixedArgs : OutVals.end());
1018  // Add a pointer to the vararg buffer.
1019  if (IsVarArg)
1020  Ops.push_back(FINode);
1021 
1022  SmallVector<EVT, 8> InTys;
1023  for (const auto &In : Ins) {
1024  assert(!In.Flags.isByVal() && "byval is not valid for return values");
1025  assert(!In.Flags.isNest() && "nest is not valid for return values");
1026  if (In.Flags.isInAlloca())
1027  fail(DL, DAG, "WebAssembly hasn't implemented inalloca return values");
1028  if (In.Flags.isInConsecutiveRegs())
1029  fail(DL, DAG, "WebAssembly hasn't implemented cons regs return values");
1030  if (In.Flags.isInConsecutiveRegsLast())
1031  fail(DL, DAG,
1032  "WebAssembly hasn't implemented cons regs last return values");
1033  // Ignore In.getNonZeroOrigAlign() because all our arguments are passed in
1034  // registers.
1035  InTys.push_back(In.VT);
1036  }
1037 
1038  if (CLI.IsTailCall) {
1039  // ret_calls do not return values to the current frame
1040  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1041  return DAG.getNode(WebAssemblyISD::RET_CALL, DL, NodeTys, Ops);
1042  }
1043 
1044  InTys.push_back(MVT::Other);
1045  SDVTList InTyList = DAG.getVTList(InTys);
1046  SDValue Res = DAG.getNode(WebAssemblyISD::CALL, DL, InTyList, Ops);
1047 
1048  for (size_t I = 0; I < Ins.size(); ++I)
1049  InVals.push_back(Res.getValue(I));
1050 
1051  // Return the chain
1052  return Res.getValue(Ins.size());
1053 }
1054 
1055 bool WebAssemblyTargetLowering::CanLowerReturn(
1056  CallingConv::ID /*CallConv*/, MachineFunction & /*MF*/, bool /*IsVarArg*/,
1057  const SmallVectorImpl<ISD::OutputArg> &Outs,
1058  LLVMContext & /*Context*/) const {
1059  // WebAssembly can only handle returning tuples with multivalue enabled
1060  return Subtarget->hasMultivalue() || Outs.size() <= 1;
1061 }
1062 
1063 SDValue WebAssemblyTargetLowering::LowerReturn(
1064  SDValue Chain, CallingConv::ID CallConv, bool /*IsVarArg*/,
1065  const SmallVectorImpl<ISD::OutputArg> &Outs,
1066  const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
1067  SelectionDAG &DAG) const {
1068  assert((Subtarget->hasMultivalue() || Outs.size() <= 1) &&
1069  "MVP WebAssembly can only return up to one value");
1070  if (!callingConvSupported(CallConv))
1071  fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
1072 
1073  SmallVector<SDValue, 4> RetOps(1, Chain);
1074  RetOps.append(OutVals.begin(), OutVals.end());
1075  Chain = DAG.getNode(WebAssemblyISD::RETURN, DL, MVT::Other, RetOps);
1076 
1077  // Record the number and types of the return values.
1078  for (const ISD::OutputArg &Out : Outs) {
1079  assert(!Out.Flags.isByVal() && "byval is not valid for return values");
1080  assert(!Out.Flags.isNest() && "nest is not valid for return values");
1081  assert(Out.IsFixed && "non-fixed return value is not valid");
1082  if (Out.Flags.isInAlloca())
1083  fail(DL, DAG, "WebAssembly hasn't implemented inalloca results");
1084  if (Out.Flags.isInConsecutiveRegs())
1085  fail(DL, DAG, "WebAssembly hasn't implemented cons regs results");
1086  if (Out.Flags.isInConsecutiveRegsLast())
1087  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last results");
1088  }
1089 
1090  return Chain;
1091 }
1092 
1093 SDValue WebAssemblyTargetLowering::LowerFormalArguments(
1094  SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
1095  const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
1096  SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
1097  if (!callingConvSupported(CallConv))
1098  fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
1099 
1100  MachineFunction &MF = DAG.getMachineFunction();
1101  auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
1102 
1103  // Set up the incoming ARGUMENTS value, which serves to represent the liveness
1104  // of the incoming values before they're represented by virtual registers.
1105  MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
1106 
1107  bool HasSwiftErrorArg = false;
1108  bool HasSwiftSelfArg = false;
1109  for (const ISD::InputArg &In : Ins) {
1110  HasSwiftSelfArg |= In.Flags.isSwiftSelf();
1111  HasSwiftErrorArg |= In.Flags.isSwiftError();
1112  if (In.Flags.isInAlloca())
1113  fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
1114  if (In.Flags.isNest())
1115  fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
1116  if (In.Flags.isInConsecutiveRegs())
1117  fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
1118  if (In.Flags.isInConsecutiveRegsLast())
1119  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
1120  // Ignore In.getNonZeroOrigAlign() because all our arguments are passed in
1121  // registers.
1122  InVals.push_back(In.Used ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
1123  DAG.getTargetConstant(InVals.size(),
1124  DL, MVT::i32))
1125  : DAG.getUNDEF(In.VT));
1126 
1127  // Record the number and types of arguments.
1128  MFI->addParam(In.VT);
1129  }
1130 
1131  // For swiftcc, emit additional swiftself and swifterror arguments
1132  // if there aren't. These additional arguments are also added for callee
1133  // signature They are necessary to match callee and caller signature for
1134  // indirect call.
1135  auto PtrVT = getPointerTy(MF.getDataLayout());
1136  if (CallConv == CallingConv::Swift) {
1137  if (!HasSwiftSelfArg) {
1138  MFI->addParam(PtrVT);
1139  }
1140  if (!HasSwiftErrorArg) {
1141  MFI->addParam(PtrVT);
1142  }
1143  }
1144  // Varargs are copied into a buffer allocated by the caller, and a pointer to
1145  // the buffer is passed as an argument.
1146  if (IsVarArg) {
1147  MVT PtrVT = getPointerTy(MF.getDataLayout());
1148  Register VarargVreg =
1150  MFI->setVarargBufferVreg(VarargVreg);
1151  Chain = DAG.getCopyToReg(
1152  Chain, DL, VarargVreg,
1153  DAG.getNode(WebAssemblyISD::ARGUMENT, DL, PtrVT,
1154  DAG.getTargetConstant(Ins.size(), DL, MVT::i32)));
1155  MFI->addParam(PtrVT);
1156  }
1157 
1158  // Record the number and types of arguments and results.
1159  SmallVector<MVT, 4> Params;
1162  MF.getFunction(), DAG.getTarget(), Params, Results);
1163  for (MVT VT : Results)
1164  MFI->addResult(VT);
1165  // TODO: Use signatures in WebAssemblyMachineFunctionInfo too and unify
1166  // the param logic here with ComputeSignatureVTs
1167  assert(MFI->getParams().size() == Params.size() &&
1168  std::equal(MFI->getParams().begin(), MFI->getParams().end(),
1169  Params.begin()));
1170 
1171  return Chain;
1172 }
1173 
1174 void WebAssemblyTargetLowering::ReplaceNodeResults(
1176  switch (N->getOpcode()) {
1178  // Do not add any results, signifying that N should not be custom lowered
1179  // after all. This happens because simd128 turns on custom lowering for
1180  // SIGN_EXTEND_INREG, but for non-vector sign extends the result might be an
1181  // illegal type.
1182  break;
1183  default:
1185  "ReplaceNodeResults not implemented for this op for WebAssembly!");
1186  }
1187 }
1188 
1189 //===----------------------------------------------------------------------===//
1190 // Custom lowering hooks.
1191 //===----------------------------------------------------------------------===//
1192 
1193 SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
1194  SelectionDAG &DAG) const {
1195  SDLoc DL(Op);
1196  switch (Op.getOpcode()) {
1197  default:
1198  llvm_unreachable("unimplemented operation lowering");
1199  return SDValue();
1200  case ISD::FrameIndex:
1201  return LowerFrameIndex(Op, DAG);
1202  case ISD::GlobalAddress:
1203  return LowerGlobalAddress(Op, DAG);
1204  case ISD::GlobalTLSAddress:
1205  return LowerGlobalTLSAddress(Op, DAG);
1206  case ISD::ExternalSymbol:
1207  return LowerExternalSymbol(Op, DAG);
1208  case ISD::JumpTable:
1209  return LowerJumpTable(Op, DAG);
1210  case ISD::BR_JT:
1211  return LowerBR_JT(Op, DAG);
1212  case ISD::VASTART:
1213  return LowerVASTART(Op, DAG);
1214  case ISD::BlockAddress:
1215  case ISD::BRIND:
1216  fail(DL, DAG, "WebAssembly hasn't implemented computed gotos");
1217  return SDValue();
1218  case ISD::RETURNADDR:
1219  return LowerRETURNADDR(Op, DAG);
1220  case ISD::FRAMEADDR:
1221  return LowerFRAMEADDR(Op, DAG);
1222  case ISD::CopyToReg:
1223  return LowerCopyToReg(Op, DAG);
1226  return LowerAccessVectorElement(Op, DAG);
1227  case ISD::INTRINSIC_VOID:
1230  return LowerIntrinsic(Op, DAG);
1232  return LowerSIGN_EXTEND_INREG(Op, DAG);
1233  case ISD::BUILD_VECTOR:
1234  return LowerBUILD_VECTOR(Op, DAG);
1235  case ISD::VECTOR_SHUFFLE:
1236  return LowerVECTOR_SHUFFLE(Op, DAG);
1237  case ISD::SETCC:
1238  return LowerSETCC(Op, DAG);
1239  case ISD::SHL:
1240  case ISD::SRA:
1241  case ISD::SRL:
1242  return LowerShift(Op, DAG);
1243  }
1244 }
1245 
1246 SDValue WebAssemblyTargetLowering::LowerCopyToReg(SDValue Op,
1247  SelectionDAG &DAG) const {
1248  SDValue Src = Op.getOperand(2);
1249  if (isa<FrameIndexSDNode>(Src.getNode())) {
1250  // CopyToReg nodes don't support FrameIndex operands. Other targets select
1251  // the FI to some LEA-like instruction, but since we don't have that, we
1252  // need to insert some kind of instruction that can take an FI operand and
1253  // produces a value usable by CopyToReg (i.e. in a vreg). So insert a dummy
1254  // local.copy between Op and its FI operand.
1255  SDValue Chain = Op.getOperand(0);
1256  SDLoc DL(Op);
1257  unsigned Reg = cast<RegisterSDNode>(Op.getOperand(1))->getReg();
1258  EVT VT = Src.getValueType();
1259  SDValue Copy(DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32
1260  : WebAssembly::COPY_I64,
1261  DL, VT, Src),
1262  0);
1263  return Op.getNode()->getNumValues() == 1
1264  ? DAG.getCopyToReg(Chain, DL, Reg, Copy)
1265  : DAG.getCopyToReg(Chain, DL, Reg, Copy,
1266  Op.getNumOperands() == 4 ? Op.getOperand(3)
1267  : SDValue());
1268  }
1269  return SDValue();
1270 }
1271 
1272 SDValue WebAssemblyTargetLowering::LowerFrameIndex(SDValue Op,
1273  SelectionDAG &DAG) const {
1274  int FI = cast<FrameIndexSDNode>(Op)->getIndex();
1275  return DAG.getTargetFrameIndex(FI, Op.getValueType());
1276 }
1277 
1278 SDValue WebAssemblyTargetLowering::LowerRETURNADDR(SDValue Op,
1279  SelectionDAG &DAG) const {
1280  SDLoc DL(Op);
1281 
1282  if (!Subtarget->getTargetTriple().isOSEmscripten()) {
1283  fail(DL, DAG,
1284  "Non-Emscripten WebAssembly hasn't implemented "
1285  "__builtin_return_address");
1286  return SDValue();
1287  }
1288 
1290  return SDValue();
1291 
1292  unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
1293  MakeLibCallOptions CallOptions;
1294  return makeLibCall(DAG, RTLIB::RETURN_ADDRESS, Op.getValueType(),
1295  {DAG.getConstant(Depth, DL, MVT::i32)}, CallOptions, DL)
1296  .first;
1297 }
1298 
1299 SDValue WebAssemblyTargetLowering::LowerFRAMEADDR(SDValue Op,
1300  SelectionDAG &DAG) const {
1301  // Non-zero depths are not supported by WebAssembly currently. Use the
1302  // legalizer's default expansion, which is to return 0 (what this function is
1303  // documented to do).
1304  if (Op.getConstantOperandVal(0) > 0)
1305  return SDValue();
1306 
1308  EVT VT = Op.getValueType();
1309  Register FP =
1311  return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), FP, VT);
1312 }
1313 
1314 SDValue
1315 WebAssemblyTargetLowering::LowerGlobalTLSAddress(SDValue Op,
1316  SelectionDAG &DAG) const {
1317  SDLoc DL(Op);
1318  const auto *GA = cast<GlobalAddressSDNode>(Op);
1319  MVT PtrVT = getPointerTy(DAG.getDataLayout());
1320 
1321  MachineFunction &MF = DAG.getMachineFunction();
1322  if (!MF.getSubtarget<WebAssemblySubtarget>().hasBulkMemory())
1323  report_fatal_error("cannot use thread-local storage without bulk memory",
1324  false);
1325 
1326  const GlobalValue *GV = GA->getGlobal();
1327 
1328  // Currently Emscripten does not support dynamic linking with threads.
1329  // Therefore, if we have thread-local storage, only the local-exec model
1330  // is possible.
1331  // TODO: remove this and implement proper TLS models once Emscripten
1332  // supports dynamic linking with threads.
1334  !Subtarget->getTargetTriple().isOSEmscripten()) {
1335  report_fatal_error("only -ftls-model=local-exec is supported for now on "
1336  "non-Emscripten OSes: variable " +
1337  GV->getName(),
1338  false);
1339  }
1340 
1341  auto GlobalGet = PtrVT == MVT::i64 ? WebAssembly::GLOBAL_GET_I64
1342  : WebAssembly::GLOBAL_GET_I32;
1343  const char *BaseName = MF.createExternalSymbolName("__tls_base");
1344 
1345  SDValue BaseAddr(
1346  DAG.getMachineNode(GlobalGet, DL, PtrVT,
1347  DAG.getTargetExternalSymbol(BaseName, PtrVT)),
1348  0);
1349 
1350  SDValue TLSOffset = DAG.getTargetGlobalAddress(
1351  GV, DL, PtrVT, GA->getOffset(), WebAssemblyII::MO_TLS_BASE_REL);
1352  SDValue SymAddr = DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT, TLSOffset);
1353 
1354  return DAG.getNode(ISD::ADD, DL, PtrVT, BaseAddr, SymAddr);
1355 }
1356 
1357 SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
1358  SelectionDAG &DAG) const {
1359  SDLoc DL(Op);
1360  const auto *GA = cast<GlobalAddressSDNode>(Op);
1361  EVT VT = Op.getValueType();
1362  assert(GA->getTargetFlags() == 0 &&
1363  "Unexpected target flags on generic GlobalAddressSDNode");
1364  if (GA->getAddressSpace() != 0)
1365  fail(DL, DAG, "WebAssembly only expects the 0 address space");
1366 
1367  unsigned OperandFlags = 0;
1368  if (isPositionIndependent()) {
1369  const GlobalValue *GV = GA->getGlobal();
1370  if (getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV)) {
1371  MachineFunction &MF = DAG.getMachineFunction();
1372  MVT PtrVT = getPointerTy(MF.getDataLayout());
1373  const char *BaseName;
1374  if (GV->getValueType()->isFunctionTy()) {
1375  BaseName = MF.createExternalSymbolName("__table_base");
1377  }
1378  else {
1379  BaseName = MF.createExternalSymbolName("__memory_base");
1381  }
1382  SDValue BaseAddr =
1383  DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT,
1384  DAG.getTargetExternalSymbol(BaseName, PtrVT));
1385 
1386  SDValue SymAddr = DAG.getNode(
1388  DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset(),
1389  OperandFlags));
1390 
1391  return DAG.getNode(ISD::ADD, DL, VT, BaseAddr, SymAddr);
1392  } else {
1394  }
1395  }
1396 
1397  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1398  DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT,
1399  GA->getOffset(), OperandFlags));
1400 }
1401 
1402 SDValue
1403 WebAssemblyTargetLowering::LowerExternalSymbol(SDValue Op,
1404  SelectionDAG &DAG) const {
1405  SDLoc DL(Op);
1406  const auto *ES = cast<ExternalSymbolSDNode>(Op);
1407  EVT VT = Op.getValueType();
1408  assert(ES->getTargetFlags() == 0 &&
1409  "Unexpected target flags on generic ExternalSymbolSDNode");
1410  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1411  DAG.getTargetExternalSymbol(ES->getSymbol(), VT));
1412 }
1413 
1414 SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op,
1415  SelectionDAG &DAG) const {
1416  // There's no need for a Wrapper node because we always incorporate a jump
1417  // table operand into a BR_TABLE instruction, rather than ever
1418  // materializing it in a register.
1419  const JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
1420  return DAG.getTargetJumpTable(JT->getIndex(), Op.getValueType(),
1421  JT->getTargetFlags());
1422 }
1423 
1424 SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op,
1425  SelectionDAG &DAG) const {
1426  SDLoc DL(Op);
1427  SDValue Chain = Op.getOperand(0);
1428  const auto *JT = cast<JumpTableSDNode>(Op.getOperand(1));
1429  SDValue Index = Op.getOperand(2);
1430  assert(JT->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");
1431 
1433  Ops.push_back(Chain);
1434  Ops.push_back(Index);
1435 
1437  const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs;
1438 
1439  // Add an operand for each case.
1440  for (auto MBB : MBBs)
1441  Ops.push_back(DAG.getBasicBlock(MBB));
1442 
1443  // Add the first MBB as a dummy default target for now. This will be replaced
1444  // with the proper default target (and the preceding range check eliminated)
1445  // if possible by WebAssemblyFixBrTableDefaults.
1446  Ops.push_back(DAG.getBasicBlock(*MBBs.begin()));
1447  return DAG.getNode(WebAssemblyISD::BR_TABLE, DL, MVT::Other, Ops);
1448 }
1449 
1450 SDValue WebAssemblyTargetLowering::LowerVASTART(SDValue Op,
1451  SelectionDAG &DAG) const {
1452  SDLoc DL(Op);
1454 
1455  auto *MFI = DAG.getMachineFunction().getInfo<WebAssemblyFunctionInfo>();
1456  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
1457 
1458  SDValue ArgN = DAG.getCopyFromReg(DAG.getEntryNode(), DL,
1459  MFI->getVarargBufferVreg(), PtrVT);
1460  return DAG.getStore(Op.getOperand(0), DL, ArgN, Op.getOperand(1),
1461  MachinePointerInfo(SV));
1462 }
1463 
1464 static SDValue getCppExceptionSymNode(SDValue Op, unsigned TagIndex,
1465  SelectionDAG &DAG) {
1466  // We only support C++ exceptions for now
1467  int Tag =
1468  cast<ConstantSDNode>(Op.getOperand(TagIndex).getNode())->getZExtValue();
1469  if (Tag != WebAssembly::CPP_EXCEPTION)
1470  llvm_unreachable("Invalid tag: We only support C++ exceptions for now");
1471  auto &MF = DAG.getMachineFunction();
1472  const auto &TLI = DAG.getTargetLoweringInfo();
1473  MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
1474  const char *SymName = MF.createExternalSymbolName("__cpp_exception");
1475  return DAG.getNode(WebAssemblyISD::Wrapper, SDLoc(Op), PtrVT,
1476  DAG.getTargetExternalSymbol(SymName, PtrVT));
1477 }
1478 
1479 SDValue WebAssemblyTargetLowering::LowerIntrinsic(SDValue Op,
1480  SelectionDAG &DAG) const {
1481  MachineFunction &MF = DAG.getMachineFunction();
1482  unsigned IntNo;
1483  switch (Op.getOpcode()) {
1484  case ISD::INTRINSIC_VOID:
1486  IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
1487  break;
1489  IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
1490  break;
1491  default:
1492  llvm_unreachable("Invalid intrinsic");
1493  }
1494  SDLoc DL(Op);
1495 
1496  switch (IntNo) {
1497  default:
1498  return SDValue(); // Don't custom lower most intrinsics.
1499 
1500  case Intrinsic::wasm_lsda: {
1501  EVT VT = Op.getValueType();
1502  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1503  MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
1504  auto &Context = MF.getMMI().getContext();
1505  MCSymbol *S = Context.getOrCreateSymbol(Twine("GCC_except_table") +
1506  Twine(MF.getFunctionNumber()));
1507  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1508  DAG.getMCSymbol(S, PtrVT));
1509  }
1510 
1511  case Intrinsic::wasm_throw: {
1512  SDValue SymNode = getCppExceptionSymNode(Op, 2, DAG);
1513  return DAG.getNode(WebAssemblyISD::THROW, DL,
1514  MVT::Other, // outchain type
1515  {
1516  Op.getOperand(0), // inchain
1517  SymNode, // exception symbol
1518  Op.getOperand(3) // thrown value
1519  });
1520  }
1521 
1522  case Intrinsic::wasm_catch: {
1523  SDValue SymNode = getCppExceptionSymNode(Op, 2, DAG);
1524  return DAG.getNode(WebAssemblyISD::CATCH, DL,
1525  {
1526  MVT::i32, // outchain type
1527  MVT::Other // return value
1528  },
1529  {
1530  Op.getOperand(0), // inchain
1531  SymNode // exception symbol
1532  });
1533  }
1534 
1535  case Intrinsic::wasm_shuffle: {
1536  // Drop in-chain and replace undefs, but otherwise pass through unchanged
1537  SDValue Ops[18];
1538  size_t OpIdx = 0;
1539  Ops[OpIdx++] = Op.getOperand(1);
1540  Ops[OpIdx++] = Op.getOperand(2);
1541  while (OpIdx < 18) {
1542  const SDValue &MaskIdx = Op.getOperand(OpIdx + 1);
1543  if (MaskIdx.isUndef() ||
1544  cast<ConstantSDNode>(MaskIdx.getNode())->getZExtValue() >= 32) {
1545  Ops[OpIdx++] = DAG.getConstant(0, DL, MVT::i32);
1546  } else {
1547  Ops[OpIdx++] = MaskIdx;
1548  }
1549  }
1550  return DAG.getNode(WebAssemblyISD::SHUFFLE, DL, Op.getValueType(), Ops);
1551  }
1552  }
1553 }
1554 
1555 SDValue
1556 WebAssemblyTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
1557  SelectionDAG &DAG) const {
1558  SDLoc DL(Op);
1559  // If sign extension operations are disabled, allow sext_inreg only if operand
1560  // is a vector extract of an i8 or i16 lane. SIMD does not depend on sign
1561  // extension operations, but allowing sext_inreg in this context lets us have
1562  // simple patterns to select extract_lane_s instructions. Expanding sext_inreg
1563  // everywhere would be simpler in this file, but would necessitate large and
1564  // brittle patterns to undo the expansion and select extract_lane_s
1565  // instructions.
1566  assert(!Subtarget->hasSignExt() && Subtarget->hasSIMD128());
1567  if (Op.getOperand(0).getOpcode() != ISD::EXTRACT_VECTOR_ELT)
1568  return SDValue();
1569 
1570  const SDValue &Extract = Op.getOperand(0);
1571  MVT VecT = Extract.getOperand(0).getSimpleValueType();
1572  if (VecT.getVectorElementType().getSizeInBits() > 32)
1573  return SDValue();
1574  MVT ExtractedLaneT =
1575  cast<VTSDNode>(Op.getOperand(1).getNode())->getVT().getSimpleVT();
1576  MVT ExtractedVecT =
1577  MVT::getVectorVT(ExtractedLaneT, 128 / ExtractedLaneT.getSizeInBits());
1578  if (ExtractedVecT == VecT)
1579  return Op;
1580 
1581  // Bitcast vector to appropriate type to ensure ISel pattern coverage
1582  const SDNode *Index = Extract.getOperand(1).getNode();
1583  if (!isa<ConstantSDNode>(Index))
1584  return SDValue();
1585  unsigned IndexVal = cast<ConstantSDNode>(Index)->getZExtValue();
1586  unsigned Scale =
1587  ExtractedVecT.getVectorNumElements() / VecT.getVectorNumElements();
1588  assert(Scale > 1);
1589  SDValue NewIndex =
1590  DAG.getConstant(IndexVal * Scale, DL, Index->getValueType(0));
1591  SDValue NewExtract = DAG.getNode(
1593  DAG.getBitcast(ExtractedVecT, Extract.getOperand(0)), NewIndex);
1594  return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, Op.getValueType(), NewExtract,
1595  Op.getOperand(1));
1596 }
1597 
1598 SDValue WebAssemblyTargetLowering::LowerBUILD_VECTOR(SDValue Op,
1599  SelectionDAG &DAG) const {
1600  SDLoc DL(Op);
1601  const EVT VecT = Op.getValueType();
1602  const EVT LaneT = Op.getOperand(0).getValueType();
1603  const size_t Lanes = Op.getNumOperands();
1604  bool CanSwizzle = VecT == MVT::v16i8;
1605 
1606  // BUILD_VECTORs are lowered to the instruction that initializes the highest
1607  // possible number of lanes at once followed by a sequence of replace_lane
1608  // instructions to individually initialize any remaining lanes.
1609 
1610  // TODO: Tune this. For example, lanewise swizzling is very expensive, so
1611  // swizzled lanes should be given greater weight.
1612 
1613  // TODO: Investigate building vectors by shuffling together vectors built by
1614  // separately specialized means.
1615 
1616  auto IsConstant = [](const SDValue &V) {
1617  return V.getOpcode() == ISD::Constant || V.getOpcode() == ISD::ConstantFP;
1618  };
1619 
1620  // Returns the source vector and index vector pair if they exist. Checks for:
1621  // (extract_vector_elt
1622  // $src,
1623  // (sign_extend_inreg (extract_vector_elt $indices, $i))
1624  // )
1625  auto GetSwizzleSrcs = [](size_t I, const SDValue &Lane) {
1626  auto Bail = std::make_pair(SDValue(), SDValue());
1627  if (Lane->getOpcode() != ISD::EXTRACT_VECTOR_ELT)
1628  return Bail;
1629  const SDValue &SwizzleSrc = Lane->getOperand(0);
1630  const SDValue &IndexExt = Lane->getOperand(1);
1631  if (IndexExt->getOpcode() != ISD::SIGN_EXTEND_INREG)
1632  return Bail;
1633  const SDValue &Index = IndexExt->getOperand(0);
1634  if (Index->getOpcode() != ISD::EXTRACT_VECTOR_ELT)
1635  return Bail;
1636  const SDValue &SwizzleIndices = Index->getOperand(0);
1637  if (SwizzleSrc.getValueType() != MVT::v16i8 ||
1638  SwizzleIndices.getValueType() != MVT::v16i8 ||
1639  Index->getOperand(1)->getOpcode() != ISD::Constant ||
1640  Index->getConstantOperandVal(1) != I)
1641  return Bail;
1642  return std::make_pair(SwizzleSrc, SwizzleIndices);
1643  };
1644 
1645  using ValueEntry = std::pair<SDValue, size_t>;
1646  SmallVector<ValueEntry, 16> SplatValueCounts;
1647 
1648  using SwizzleEntry = std::pair<std::pair<SDValue, SDValue>, size_t>;
1649  SmallVector<SwizzleEntry, 16> SwizzleCounts;
1650 
1651  auto AddCount = [](auto &Counts, const auto &Val) {
1652  auto CountIt =
1653  llvm::find_if(Counts, [&Val](auto E) { return E.first == Val; });
1654  if (CountIt == Counts.end()) {
1655  Counts.emplace_back(Val, 1);
1656  } else {
1657  CountIt->second++;
1658  }
1659  };
1660 
1661  auto GetMostCommon = [](auto &Counts) {
1662  auto CommonIt =
1663  std::max_element(Counts.begin(), Counts.end(),
1664  [](auto A, auto B) { return A.second < B.second; });
1665  assert(CommonIt != Counts.end() && "Unexpected all-undef build_vector");
1666  return *CommonIt;
1667  };
1668 
1669  size_t NumConstantLanes = 0;
1670 
1671  // Count eligible lanes for each type of vector creation op
1672  for (size_t I = 0; I < Lanes; ++I) {
1673  const SDValue &Lane = Op->getOperand(I);
1674  if (Lane.isUndef())
1675  continue;
1676 
1677  AddCount(SplatValueCounts, Lane);
1678 
1679  if (IsConstant(Lane)) {
1680  NumConstantLanes++;
1681  } else if (CanSwizzle) {
1682  auto SwizzleSrcs = GetSwizzleSrcs(I, Lane);
1683  if (SwizzleSrcs.first)
1684  AddCount(SwizzleCounts, SwizzleSrcs);
1685  }
1686  }
1687 
1688  SDValue SplatValue;
1689  size_t NumSplatLanes;
1690  std::tie(SplatValue, NumSplatLanes) = GetMostCommon(SplatValueCounts);
1691 
1692  SDValue SwizzleSrc;
1693  SDValue SwizzleIndices;
1694  size_t NumSwizzleLanes = 0;
1695  if (SwizzleCounts.size())
1696  std::forward_as_tuple(std::tie(SwizzleSrc, SwizzleIndices),
1697  NumSwizzleLanes) = GetMostCommon(SwizzleCounts);
1698 
1699  // Predicate returning true if the lane is properly initialized by the
1700  // original instruction
1701  std::function<bool(size_t, const SDValue &)> IsLaneConstructed;
1702  SDValue Result;
1703  // Prefer swizzles over vector consts over splats
1704  if (NumSwizzleLanes >= NumSplatLanes &&
1705  (!Subtarget->hasUnimplementedSIMD128() ||
1706  NumSwizzleLanes >= NumConstantLanes)) {
1707  Result = DAG.getNode(WebAssemblyISD::SWIZZLE, DL, VecT, SwizzleSrc,
1708  SwizzleIndices);
1709  auto Swizzled = std::make_pair(SwizzleSrc, SwizzleIndices);
1710  IsLaneConstructed = [&, Swizzled](size_t I, const SDValue &Lane) {
1711  return Swizzled == GetSwizzleSrcs(I, Lane);
1712  };
1713  } else if (NumConstantLanes >= NumSplatLanes &&
1714  Subtarget->hasUnimplementedSIMD128()) {
1715  // If we support v128.const, emit it directly
1716  SmallVector<SDValue, 16> ConstLanes;
1717  for (const SDValue &Lane : Op->op_values()) {
1718  if (IsConstant(Lane)) {
1719  ConstLanes.push_back(Lane);
1720  } else if (LaneT.isFloatingPoint()) {
1721  ConstLanes.push_back(DAG.getConstantFP(0, DL, LaneT));
1722  } else {
1723  ConstLanes.push_back(DAG.getConstant(0, DL, LaneT));
1724  }
1725  }
1726  Result = DAG.getBuildVector(VecT, DL, ConstLanes);
1727  IsLaneConstructed = [&IsConstant](size_t _, const SDValue &Lane) {
1728  return IsConstant(Lane);
1729  };
1730  } else if (NumConstantLanes >= NumSplatLanes && VecT.isInteger()) {
1731  // Otherwise, if this is an integer vector, pack the lane values together so
1732  // we can construct the 128-bit constant from a pair of i64s using a splat
1733  // followed by at most one i64x2.replace_lane. Also keep track of the lanes
1734  // that actually matter so we can avoid the replace_lane in more cases.
1735  std::array<uint64_t, 2> I64s{{0, 0}};
1736  std::array<uint64_t, 2> ConstLaneMasks{{0, 0}};
1737  size_t LaneBits = 128 / Lanes;
1738  size_t HalfLanes = Lanes / 2;
1739  for (size_t I = 0; I < Lanes; ++I) {
1740  const SDValue &Lane = Op.getOperand(I);
1741  if (IsConstant(Lane)) {
1742  // How much we need to shift Val to position it in an i64
1743  auto Shift = LaneBits * (I % HalfLanes);
1744  auto Mask = maskTrailingOnes<uint64_t>(LaneBits);
1745  auto Val = cast<ConstantSDNode>(Lane.getNode())->getZExtValue() & Mask;
1746  I64s[I / HalfLanes] |= Val << Shift;
1747  ConstLaneMasks[I / HalfLanes] |= Mask << Shift;
1748  }
1749  }
1750  // Check whether all constant lanes in the second half of the vector are
1751  // equivalent in the first half or vice versa to determine whether splatting
1752  // either side will be sufficient to materialize the constant. As a special
1753  // case, if the first and second halves have no constant lanes in common, we
1754  // can just combine them.
1755  bool FirstHalfSufficient = (I64s[0] & ConstLaneMasks[1]) == I64s[1];
1756  bool SecondHalfSufficient = (I64s[1] & ConstLaneMasks[0]) == I64s[0];
1757  bool CombinedSufficient = (ConstLaneMasks[0] & ConstLaneMasks[1]) == 0;
1758 
1759  uint64_t Splatted;
1760  if (SecondHalfSufficient) {
1761  Splatted = I64s[1];
1762  } else if (CombinedSufficient) {
1763  Splatted = I64s[0] | I64s[1];
1764  } else {
1765  Splatted = I64s[0];
1766  }
1767 
1769  DAG.getConstant(Splatted, DL, MVT::i64));
1770  if (!FirstHalfSufficient && !SecondHalfSufficient && !CombinedSufficient) {
1772  DAG.getConstant(I64s[1], DL, MVT::i64),
1773  DAG.getConstant(1, DL, MVT::i32));
1774  }
1775  Result = DAG.getBitcast(VecT, Result);
1776  IsLaneConstructed = [&IsConstant](size_t _, const SDValue &Lane) {
1777  return IsConstant(Lane);
1778  };
1779  } else {
1780  // Use a splat, but possibly a load_splat
1781  LoadSDNode *SplattedLoad;
1782  if ((SplattedLoad = dyn_cast<LoadSDNode>(SplatValue)) &&
1783  SplattedLoad->getMemoryVT() == VecT.getVectorElementType()) {
1785  WebAssemblyISD::LOAD_SPLAT, DL, DAG.getVTList(VecT),
1786  {SplattedLoad->getChain(), SplattedLoad->getBasePtr(),
1787  SplattedLoad->getOffset()},
1788  SplattedLoad->getMemoryVT(), SplattedLoad->getMemOperand());
1789  } else {
1790  Result = DAG.getSplatBuildVector(VecT, DL, SplatValue);
1791  }
1792  IsLaneConstructed = [&SplatValue](size_t _, const SDValue &Lane) {
1793  return Lane == SplatValue;
1794  };
1795  }
1796 
1797  assert(Result);
1798  assert(IsLaneConstructed);
1799 
1800  // Add replace_lane instructions for any unhandled values
1801  for (size_t I = 0; I < Lanes; ++I) {
1802  const SDValue &Lane = Op->getOperand(I);
1803  if (!Lane.isUndef() && !IsLaneConstructed(I, Lane))
1804  Result = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VecT, Result, Lane,
1805  DAG.getConstant(I, DL, MVT::i32));
1806  }
1807 
1808  return Result;
1809 }
1810 
1811 SDValue
1812 WebAssemblyTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
1813  SelectionDAG &DAG) const {
1814  SDLoc DL(Op);
1815  ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(Op.getNode())->getMask();
1816  MVT VecType = Op.getOperand(0).getSimpleValueType();
1817  assert(VecType.is128BitVector() && "Unexpected shuffle vector type");
1818  size_t LaneBytes = VecType.getVectorElementType().getSizeInBits() / 8;
1819 
1820  // Space for two vector args and sixteen mask indices
1821  SDValue Ops[18];
1822  size_t OpIdx = 0;
1823  Ops[OpIdx++] = Op.getOperand(0);
1824  Ops[OpIdx++] = Op.getOperand(1);
1825 
1826  // Expand mask indices to byte indices and materialize them as operands
1827  for (int M : Mask) {
1828  for (size_t J = 0; J < LaneBytes; ++J) {
1829  // Lower undefs (represented by -1 in mask) to zero
1830  uint64_t ByteIndex = M == -1 ? 0 : (uint64_t)M * LaneBytes + J;
1831  Ops[OpIdx++] = DAG.getConstant(ByteIndex, DL, MVT::i32);
1832  }
1833  }
1834 
1835  return DAG.getNode(WebAssemblyISD::SHUFFLE, DL, Op.getValueType(), Ops);
1836 }
1837 
1838 SDValue WebAssemblyTargetLowering::LowerSETCC(SDValue Op,
1839  SelectionDAG &DAG) const {
1840  SDLoc DL(Op);
1841  // The legalizer does not know how to expand the comparison modes of i64x2
1842  // vectors because no comparison modes are supported. We could solve this by
1843  // expanding all i64x2 SETCC nodes, but that seems to expand f64x2 SETCC nodes
1844  // (which return i64x2 results) as well. So instead we manually unroll i64x2
1845  // comparisons here.
1846  assert(Op->getOperand(0)->getSimpleValueType(0) == MVT::v2i64);
1847  SmallVector<SDValue, 2> LHS, RHS;
1848  DAG.ExtractVectorElements(Op->getOperand(0), LHS);
1849  DAG.ExtractVectorElements(Op->getOperand(1), RHS);
1850  const SDValue &CC = Op->getOperand(2);
1851  auto MakeLane = [&](unsigned I) {
1852  return DAG.getNode(ISD::SELECT_CC, DL, MVT::i64, LHS[I], RHS[I],
1853  DAG.getConstant(uint64_t(-1), DL, MVT::i64),
1854  DAG.getConstant(uint64_t(0), DL, MVT::i64), CC);
1855  };
1856  return DAG.getBuildVector(Op->getValueType(0), DL,
1857  {MakeLane(0), MakeLane(1)});
1858 }
1859 
1860 SDValue
1861 WebAssemblyTargetLowering::LowerAccessVectorElement(SDValue Op,
1862  SelectionDAG &DAG) const {
1863  // Allow constant lane indices, expand variable lane indices
1864  SDNode *IdxNode = Op.getOperand(Op.getNumOperands() - 1).getNode();
1865  if (isa<ConstantSDNode>(IdxNode) || IdxNode->isUndef())
1866  return Op;
1867  else
1868  // Perform default expansion
1869  return SDValue();
1870 }
1871 
1873  EVT LaneT = Op.getSimpleValueType().getVectorElementType();
1874  // 32-bit and 64-bit unrolled shifts will have proper semantics
1875  if (LaneT.bitsGE(MVT::i32))
1876  return DAG.UnrollVectorOp(Op.getNode());
1877  // Otherwise mask the shift value to get proper semantics from 32-bit shift
1878  SDLoc DL(Op);
1879  size_t NumLanes = Op.getSimpleValueType().getVectorNumElements();
1880  SDValue Mask = DAG.getConstant(LaneT.getSizeInBits() - 1, DL, MVT::i32);
1881  unsigned ShiftOpcode = Op.getOpcode();
1882  SmallVector<SDValue, 16> ShiftedElements;
1883  DAG.ExtractVectorElements(Op.getOperand(0), ShiftedElements, 0, 0, MVT::i32);
1884  SmallVector<SDValue, 16> ShiftElements;
1885  DAG.ExtractVectorElements(Op.getOperand(1), ShiftElements, 0, 0, MVT::i32);
1886  SmallVector<SDValue, 16> UnrolledOps;
1887  for (size_t i = 0; i < NumLanes; ++i) {
1888  SDValue MaskedShiftValue =
1889  DAG.getNode(ISD::AND, DL, MVT::i32, ShiftElements[i], Mask);
1890  SDValue ShiftedValue = ShiftedElements[i];
1891  if (ShiftOpcode == ISD::SRA)
1892  ShiftedValue = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i32,
1893  ShiftedValue, DAG.getValueType(LaneT));
1894  UnrolledOps.push_back(
1895  DAG.getNode(ShiftOpcode, DL, MVT::i32, ShiftedValue, MaskedShiftValue));
1896  }
1897  return DAG.getBuildVector(Op.getValueType(), DL, UnrolledOps);
1898 }
1899 
1900 SDValue WebAssemblyTargetLowering::LowerShift(SDValue Op,
1901  SelectionDAG &DAG) const {
1902  SDLoc DL(Op);
1903 
1904  // Only manually lower vector shifts
1905  assert(Op.getSimpleValueType().isVector());
1906 
1907  auto ShiftVal = DAG.getSplatValue(Op.getOperand(1));
1908  if (!ShiftVal)
1909  return unrollVectorShift(Op, DAG);
1910 
1911  // Use anyext because none of the high bits can affect the shift
1912  ShiftVal = DAG.getAnyExtOrTrunc(ShiftVal, DL, MVT::i32);
1913 
1914  unsigned Opcode;
1915  switch (Op.getOpcode()) {
1916  case ISD::SHL:
1917  Opcode = WebAssemblyISD::VEC_SHL;
1918  break;
1919  case ISD::SRA:
1920  Opcode = WebAssemblyISD::VEC_SHR_S;
1921  break;
1922  case ISD::SRL:
1923  Opcode = WebAssemblyISD::VEC_SHR_U;
1924  break;
1925  default:
1926  llvm_unreachable("unexpected opcode");
1927  }
1928 
1929  return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(0), ShiftVal);
1930 }
1931 
1932 //===----------------------------------------------------------------------===//
1933 // Custom DAG combine hooks
1934 //===----------------------------------------------------------------------===//
1935 static SDValue
1937  auto &DAG = DCI.DAG;
1938  auto Shuffle = cast<ShuffleVectorSDNode>(N);
1939 
1940  // Hoist vector bitcasts that don't change the number of lanes out of unary
1941  // shuffles, where they are less likely to get in the way of other combines.
1942  // (shuffle (vNxT1 (bitcast (vNxT0 x))), undef, mask) ->
1943  // (vNxT1 (bitcast (vNxT0 (shuffle x, undef, mask))))
1944  SDValue Bitcast = N->getOperand(0);
1945  if (Bitcast.getOpcode() != ISD::BITCAST)
1946  return SDValue();
1947  if (!N->getOperand(1).isUndef())
1948  return SDValue();
1949  SDValue CastOp = Bitcast.getOperand(0);
1950  MVT SrcType = CastOp.getSimpleValueType();
1951  MVT DstType = Bitcast.getSimpleValueType();
1952  if (!SrcType.is128BitVector() ||
1953  SrcType.getVectorNumElements() != DstType.getVectorNumElements())
1954  return SDValue();
1955  SDValue NewShuffle = DAG.getVectorShuffle(
1956  SrcType, SDLoc(N), CastOp, DAG.getUNDEF(SrcType), Shuffle->getMask());
1957  return DAG.getBitcast(DstType, NewShuffle);
1958 }
1959 
1962  auto &DAG = DCI.DAG;
1963  assert(N->getOpcode() == ISD::SIGN_EXTEND ||
1964  N->getOpcode() == ISD::ZERO_EXTEND);
1965 
1966  // Combine ({s,z}ext (extract_subvector src, i)) into a widening operation if
1967  // possible before the extract_subvector can be expanded.
1968  auto Extract = N->getOperand(0);
1969  if (Extract.getOpcode() != ISD::EXTRACT_SUBVECTOR)
1970  return SDValue();
1971  auto Source = Extract.getOperand(0);
1972  auto *IndexNode = dyn_cast<ConstantSDNode>(Extract.getOperand(1));
1973  if (IndexNode == nullptr)
1974  return SDValue();
1975  auto Index = IndexNode->getZExtValue();
1976 
1977  // Only v8i8 and v4i16 extracts can be widened, and only if the extracted
1978  // subvector is the low or high half of its source.
1979  EVT ResVT = N->getValueType(0);
1980  if (ResVT == MVT::v8i16) {
1981  if (Extract.getValueType() != MVT::v8i8 ||
1982  Source.getValueType() != MVT::v16i8 || (Index != 0 && Index != 8))
1983  return SDValue();
1984  } else if (ResVT == MVT::v4i32) {
1985  if (Extract.getValueType() != MVT::v4i16 ||
1986  Source.getValueType() != MVT::v8i16 || (Index != 0 && Index != 4))
1987  return SDValue();
1988  } else {
1989  return SDValue();
1990  }
1991 
1992  bool IsSext = N->getOpcode() == ISD::SIGN_EXTEND;
1993  bool IsLow = Index == 0;
1994 
1995  unsigned Op = IsSext ? (IsLow ? WebAssemblyISD::WIDEN_LOW_S
1996  : WebAssemblyISD::WIDEN_HIGH_S)
1997  : (IsLow ? WebAssemblyISD::WIDEN_LOW_U
1998  : WebAssemblyISD::WIDEN_HIGH_U);
1999 
2000  return DAG.getNode(Op, SDLoc(N), ResVT, Source);
2001 }
2002 
2003 SDValue
2004 WebAssemblyTargetLowering::PerformDAGCombine(SDNode *N,
2005  DAGCombinerInfo &DCI) const {
2006  switch (N->getOpcode()) {
2007  default:
2008  return SDValue();
2009  case ISD::VECTOR_SHUFFLE:
2010  return performVECTOR_SHUFFLECombine(N, DCI);
2011  case ISD::SIGN_EXTEND:
2012  case ISD::ZERO_EXTEND:
2013  return performVectorWidenCombine(N, DCI);
2014  }
2015 }
void setFrameAddressIsTaken(bool T)
uint64_t CallInst * C
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
Definition: ISDOpcodes.h:790
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:610
This file defines the interfaces that WebAssembly uses to lower LLVM code into a selection DAG.
SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, uint64_t Size=0, const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
bool isOSEmscripten() const
Tests whether the OS is Emscripten.
Definition: Triple.h:612
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:111
EVT getValueType() const
Return the ValueType of the referenced return value.
ThreadLocalMode getThreadLocalMode() const
Definition: GlobalValue.h:252
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...
const SDValue & getOffset() const
static Type * getDoubleTy(LLVMContext &C)
Definition: Type.cpp:185
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.
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition: ISDOpcodes.h:541
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
BR_CC - Conditional branch.
Definition: ISDOpcodes.h:905
This class represents lattice values for constants.
Definition: AllocatorList.h:23
iterator_range< mop_iterator > uses()
Returns a range that includes all operands that are register uses.
Definition: MachineInstr.h:622
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:853
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition: ISDOpcodes.h:550
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.
const SDValue & getBasePtr() const
Carry-setting nodes for multiple precision addition and subtraction.
Definition: ISDOpcodes.h:262
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:196
void setNoStrip() const
Definition: MCSymbolWasm.h:62
const Value * stripPointerCastsAndAliases() const
Strip off pointer casts, all-zero GEPs, address space casts, and aliases.
Definition: Value.cpp:634
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:954
This class represents a function call, abstracting a target machine'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:278
SDValue getBasicBlock(MachineBasicBlock *MBB)
unsigned getVectorNumElements() const
const SDValue & getChain() 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
bool isInteger() const
Return true if this is an integer or a vector integer type.
Definition: ValueTypes.h:136
F(f)
MachineModuleInfo & getMMI() const
Align getNonZeroOrigAlign() const
[US]{MIN/MAX} - Binary minimum or maximum or signed or unsigned integers.
Definition: ISDOpcodes.h:575
an instruction that atomically reads a memory location, combines it with another value,...
Definition: Instructions.h:702
Hexagon Common GEP
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.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
static MachineBasicBlock * LowerCallResults(MachineInstr &CallResults, DebugLoc DL, MachineBasicBlock *BB, const TargetInstrInfo &TII)
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition: ISDOpcodes.h:643
SDValue getMCSymbol(MCSymbol *Sym, EVT VT)
Register getFrameRegister(const MachineFunction &MF) const override
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
Function & getFunction()
Return the LLVM function that this machine code represents.
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition: ISDOpcodes.h:185
MachineBasicBlock & MBB
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
Definition: ISDOpcodes.h:248
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition: ValueTypes.h:131
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
Definition: ISDOpcodes.h:664
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
static SDValue performVectorWidenCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performVECTOR_SHUFFLECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
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:184
#define INT64_MIN
Definition: DataTypes.h:74
Shift and rotation operations.
Definition: ISDOpcodes.h:606
Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
Definition: ValueTypes.cpp:178
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition: ISDOpcodes.h:589
A Use represents the edge between a Value definition and its users.
Definition: Use.h:44
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),...
BinOp getOperation() const
Definition: Instructions.h:781
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
Definition: ISDOpcodes.h:222
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:43
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
Bitwise or logical AND of integers.
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
Definition: ISDOpcodes.h:196
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
Definition: SelectionDAG.h:700
void setCondCodeAction(ISD::CondCode CC, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn'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:475
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
Definition: SelectionDAG.h:523
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:447
std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:80
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:87
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's that has been intern'd by a SelectionDAG.
STACKSAVE - STACKSAVE has one operand, an input chain.
Definition: ISDOpcodes.h:950
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Definition: FastISel.h:65
This file declares the WebAssembly-specific subclass of TargetMachine.
MachineFunction & getMachineFunction() const
Definition: SelectionDAG.h:444
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition: ISDOpcodes.h:688
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:695
const TargetMachine & getTarget() const
Definition: SelectionDAG.h:448
const MCContext & getContext() const
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:232
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:160
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
Definition: SelectionDAG.h:950
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
Definition: SelectionDAG.h:644
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:814
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition: ISDOpcodes.h:177
MVT getVectorElementType() const
Analysis containing CSE Info
Definition: CSEInfo.cpp:25
void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc, const Function &ContextFunc, const TargetMachine &TM, SmallVectorImpl< MVT > &Params, SmallVectorImpl< MVT > &Results)
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 "...".
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition: ISDOpcodes.h:734
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition: ISDOpcodes.h:485
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)
SDValue getSplatValue(SDValue V)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
bool is128BitVector() const
Return true if this is a 128-bit vector type.
MCContext & getContext() const
This file contains the declaration of the WebAssembly-specific utility functions.
The memory access is volatile.
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:254
SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
void addLiveIn(MCRegister Reg, Register vreg=Register())
addLiveIn - Add the specified register as a live-in.
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition: ISDOpcodes.h:192
Control flow instructions. These all have token chains.
Definition: ISDOpcodes.h:879
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:58
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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:68
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
void setTargetDAGCombine(ISD::NodeType NT)
Targets should invoke this method for each target independent node that they want to provide a custom...
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:983
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:494
Carry-using nodes for multiple precision addition and subtraction.
Definition: ISDOpcodes.h:272
OperandFlags
These are flags set on operands, but should be considered private, all access should go through the M...
Definition: MCInstrDesc.h:49
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...
iterator_range< mop_iterator > defs()
Returns a range over all explicit operands that are register definitions.
Definition: MachineInstr.h:611
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:1030
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Fast - This calling convention attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:42
DEBUGTRAP - Trap intended to get the attention of a debugger.
Definition: ISDOpcodes.h:1033
self_iterator getIterator()
Definition: ilist_node.h:81
constexpr unsigned BitWidth
Definition: BitmaskEnum.h:147
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
Definition: ISDOpcodes.h:974
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:296
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...
uint64_t Align
static unsigned NumFixedArgs
Extended Value Type.
Definition: ValueTypes.h:35
uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
Definition: MathExtras.h:684
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition: ValueTypes.h:333
bool isPositionIndependent() const
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.
Sum of integers.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
unsigned getAddressSpace() const
The memory access writes data.
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.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition: ISDOpcodes.h:320
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition: ISDOpcodes.h:52
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:450
uint64_t Offset
Perform the operation on a different, but equivalently sized type.
Definition: LegalizerInfo.h:73
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:690
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:350
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition: ISDOpcodes.h:505
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition: ValueTypes.h:290
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:223
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1116
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
Definition: SelectionDAG.h:797
Provides information about what library functions are available for the current target.
Align getNonZeroByValAlign() const
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
Definition: ValueTypes.h:94
uint32_t Index
Byte Swap and Counting operators.
Definition: ISDOpcodes.h:615
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
Definition: ISDOpcodes.h:800
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:914
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, SDValue N)
Definition: SelectionDAG.h:742
static mvt_range integer_valuetypes()
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:944
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:165
EVT getMemoryVT() const
Return the type of the in-memory value.
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)
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition: ISDOpcodes.h:678
MCSymbolWasm * getOrCreateFunctionTableSymbol(MCContext &Ctx, const StringRef &Name)
Returns the operand number of a callee, assuming the argument is a call instruction.
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition: ISDOpcodes.h:470
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:608
const WebAssemblyRegisterInfo * getRegisterInfo() const override
Flags
Flags values. These may be or'd together.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
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:888
Representation of each machine instruction.
Definition: MachineInstr.h:62
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
Definition: ISDOpcodes.h:979
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
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:146
bool isFunctionTy() const
True if this is an instance of FunctionType.
Definition: Type.h:220
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:581
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
Definition: SelectionDAG.h:768
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:243
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition: ISDOpcodes.h:696
bool isInConsecutiveRegsLast() const
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:295
SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, bool isTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo)
#define I(x, y, z)
Definition: MD5.cpp:59
#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.
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.
Type * getValueType() const
Definition: GlobalValue.h:273
static CCValAssign getMem(unsigned ValNo, MVT ValVT, unsigned Offset, MVT LocVT, LocInfo HTP)
FSINCOS - Compute both fsin and fcos as a single operation.
Definition: ISDOpcodes.h:857
SDValue getValue(unsigned R) const
void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
static SDValue getCppExceptionSymNode(SDValue Op, unsigned TagIndex, SelectionDAG &DAG)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
MachineInstr * CreateMachineInstr(const MCInstrDesc &MCID, const DebugLoc &DL, bool NoImplicit=false)
CreateMachineInstr - Allocate a new MachineInstr.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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:572
LLVM Value Representation.
Definition: Value.h:75
void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty, SmallVectorImpl< MVT > &ValueVTs)
FMA - Perform a * b + c with no intermediate rounding step.
Definition: ISDOpcodes.h:460
SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
SDValue getValueType(EVT)
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
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:77
static mvt_range fixedlen_vector_valuetypes()
print Print MemDeps of function
auto drop_begin(T &&RangeOrContainer, size_t N)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition: STLExtras.h:275
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
SetCC operator - This evaluates to a true value iff the condition is true.
Definition: ISDOpcodes.h:651
void RemoveOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
const WebAssemblyInstrInfo * getInstrInfo() const override
Conversion operators.
Definition: ISDOpcodes.h:675
const SDValue & getOperand(unsigned i) const
bool verifyReturnAddressArgumentIsConstant(SDValue Op, SelectionDAG &DAG) const
Calling convention for emscripten __invoke_* functions.
Definition: CallingConv.h:242
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:485
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1525
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
Definition: ValueTypes.h:65
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:454
C - The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition: ISDOpcodes.h:570
BRIND - Indirect branch.
Definition: ISDOpcodes.h:884
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:873