Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
Line
Count
Source (jump to first uncovered line)
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
14
#include "WebAssemblyISelLowering.h"
15
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
16
#include "WebAssemblyMachineFunctionInfo.h"
17
#include "WebAssemblySubtarget.h"
18
#include "WebAssemblyTargetMachine.h"
19
#include "llvm/CodeGen/Analysis.h"
20
#include "llvm/CodeGen/CallingConvLower.h"
21
#include "llvm/CodeGen/MachineInstrBuilder.h"
22
#include "llvm/CodeGen/MachineJumpTableInfo.h"
23
#include "llvm/CodeGen/MachineModuleInfo.h"
24
#include "llvm/CodeGen/MachineRegisterInfo.h"
25
#include "llvm/CodeGen/SelectionDAG.h"
26
#include "llvm/CodeGen/WasmEHFuncInfo.h"
27
#include "llvm/IR/DiagnosticInfo.h"
28
#include "llvm/IR/DiagnosticPrinter.h"
29
#include "llvm/IR/Function.h"
30
#include "llvm/IR/Intrinsics.h"
31
#include "llvm/Support/Debug.h"
32
#include "llvm/Support/ErrorHandling.h"
33
#include "llvm/Support/raw_ostream.h"
34
#include "llvm/Target/TargetOptions.h"
35
using namespace llvm;
36
37
#define DEBUG_TYPE "wasm-lower"
38
39
WebAssemblyTargetLowering::WebAssemblyTargetLowering(
40
    const TargetMachine &TM, const WebAssemblySubtarget &STI)
41
546
    : TargetLowering(TM), Subtarget(&STI) {
42
546
  auto MVTPtr = Subtarget->hasAddr64() ? 
MVT::i647
:
MVT::i32539
;
43
546
44
546
  // Booleans always contain 0 or 1.
45
546
  setBooleanContents(ZeroOrOneBooleanContent);
46
546
  // Except in SIMD vectors
47
546
  setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);
48
546
  // We don't know the microarchitecture here, so just reduce register pressure.
49
546
  setSchedulingPreference(Sched::RegPressure);
50
546
  // Tell ISel that we have a stack pointer.
51
546
  setStackPointerRegisterToSaveRestore(
52
546
      Subtarget->hasAddr64() ? 
WebAssembly::SP647
:
WebAssembly::SP32539
);
53
546
  // Set up the register classes.
54
546
  addRegisterClass(MVT::i32, &WebAssembly::I32RegClass);
55
546
  addRegisterClass(MVT::i64, &WebAssembly::I64RegClass);
56
546
  addRegisterClass(MVT::f32, &WebAssembly::F32RegClass);
57
546
  addRegisterClass(MVT::f64, &WebAssembly::F64RegClass);
58
546
  if (Subtarget->hasSIMD128()) {
59
88
    addRegisterClass(MVT::v16i8, &WebAssembly::V128RegClass);
60
88
    addRegisterClass(MVT::v8i16, &WebAssembly::V128RegClass);
61
88
    addRegisterClass(MVT::v4i32, &WebAssembly::V128RegClass);
62
88
    addRegisterClass(MVT::v4f32, &WebAssembly::V128RegClass);
63
88
  }
64
546
  if (Subtarget->hasUnimplementedSIMD128()) {
65
40
    addRegisterClass(MVT::v2i64, &WebAssembly::V128RegClass);
66
40
    addRegisterClass(MVT::v2f64, &WebAssembly::V128RegClass);
67
40
  }
68
546
  // Compute derived properties from the register classes.
69
546
  computeRegisterProperties(Subtarget->getRegisterInfo());
70
546
71
546
  setOperationAction(ISD::GlobalAddress, MVTPtr, Custom);
72
546
  setOperationAction(ISD::ExternalSymbol, MVTPtr, Custom);
73
546
  setOperationAction(ISD::JumpTable, MVTPtr, Custom);
74
546
  setOperationAction(ISD::BlockAddress, MVTPtr, Custom);
75
546
  setOperationAction(ISD::BRIND, MVT::Other, Custom);
76
546
77
546
  // Take the default expansion for va_arg, va_copy, and va_end. There is no
78
546
  // default action for va_start, so we do that custom.
79
546
  setOperationAction(ISD::VASTART, MVT::Other, Custom);
80
546
  setOperationAction(ISD::VAARG, MVT::Other, Expand);
81
546
  setOperationAction(ISD::VACOPY, MVT::Other, Expand);
82
546
  setOperationAction(ISD::VAEND, MVT::Other, Expand);
83
546
84
2.18k
  for (auto T : {MVT::f32, MVT::f64, MVT::v4f32, MVT::v2f64}) {
85
2.18k
    // Don't expand the floating-point types to constant pools.
86
2.18k
    setOperationAction(ISD::ConstantFP, T, Legal);
87
2.18k
    // Expand floating-point comparisons.
88
2.18k
    for (auto CC : {ISD::SETO, ISD::SETUO, ISD::SETUEQ, ISD::SETONE,
89
2.18k
                    ISD::SETULT, ISD::SETULE, ISD::SETUGT, ISD::SETUGE})
90
17.4k
      setCondCodeAction(CC, T, Expand);
91
2.18k
    // Expand floating-point library function operators.
92
2.18k
    for (auto Op :
93
2.18k
         {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW, ISD::FREM, ISD::FMA})
94
13.1k
      setOperationAction(Op, T, Expand);
95
2.18k
    // Note supported floating-point library function operators that otherwise
96
2.18k
    // default to expand.
97
2.18k
    for (auto Op :
98
2.18k
         {ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FNEARBYINT, ISD::FRINT})
99
10.9k
      setOperationAction(Op, T, Legal);
100
2.18k
    // Support minimum and maximum, which otherwise default to expand.
101
2.18k
    setOperationAction(ISD::FMINIMUM, T, Legal);
102
2.18k
    setOperationAction(ISD::FMAXIMUM, T, Legal);
103
2.18k
    // WebAssembly currently has no builtin f16 support.
104
2.18k
    setOperationAction(ISD::FP16_TO_FP, T, Expand);
105
2.18k
    setOperationAction(ISD::FP_TO_FP16, T, Expand);
106
2.18k
    setLoadExtAction(ISD::EXTLOAD, T, MVT::f16, Expand);
107
2.18k
    setTruncStoreAction(T, MVT::f16, Expand);
108
2.18k
  }
109
546
110
546
  // Expand unavailable integer operations.
111
546
  for (auto Op :
112
546
       {ISD::BSWAP, ISD::SMUL_LOHI, ISD::UMUL_LOHI, ISD::MULHS, ISD::MULHU,
113
546
        ISD::SDIVREM, ISD::UDIVREM, ISD::SHL_PARTS, ISD::SRA_PARTS,
114
7.64k
        ISD::SRL_PARTS, ISD::ADDC, ISD::ADDE, ISD::SUBC, ISD::SUBE}) {
115
7.64k
    for (auto T : {MVT::i32, MVT::i64})
116
15.2k
      setOperationAction(Op, T, Expand);
117
7.64k
    if (Subtarget->hasSIMD128())
118
1.23k
      for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
119
3.69k
        setOperationAction(Op, T, Expand);
120
7.64k
    if (Subtarget->hasUnimplementedSIMD128())
121
560
      setOperationAction(Op, MVT::v2i64, Expand);
122
7.64k
  }
123
546
124
546
  // SIMD-specific configuration
125
546
  if (Subtarget->hasSIMD128()) {
126
88
    // Support saturating add for i8x16 and i16x8
127
88
    for (auto Op : {ISD::SADDSAT, ISD::UADDSAT})
128
176
      for (auto T : {MVT::v16i8, MVT::v8i16})
129
352
        setOperationAction(Op, T, Legal);
130
88
131
88
    // Custom lower BUILD_VECTORs to minimize number of replace_lanes
132
88
    for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32})
133
352
      setOperationAction(ISD::BUILD_VECTOR, T, Custom);
134
88
    if (Subtarget->hasUnimplementedSIMD128())
135
40
      for (auto T : {MVT::v2i64, MVT::v2f64})
136
80
        setOperationAction(ISD::BUILD_VECTOR, T, Custom);
137
88
138
88
    // We have custom shuffle lowering to expose the shuffle mask
139
88
    for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32})
140
352
      setOperationAction(ISD::VECTOR_SHUFFLE, T, Custom);
141
88
    if (Subtarget->hasUnimplementedSIMD128())
142
40
      for (auto T: {MVT::v2i64, MVT::v2f64})
143
80
        setOperationAction(ISD::VECTOR_SHUFFLE, T, Custom);
144
88
145
88
    // Custom lowering since wasm shifts must have a scalar shift amount
146
264
    for (auto Op : {ISD::SHL, ISD::SRA, ISD::SRL}) {
147
264
      for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
148
792
        setOperationAction(Op, T, Custom);
149
264
      if (Subtarget->hasUnimplementedSIMD128())
150
120
        setOperationAction(Op, MVT::v2i64, Custom);
151
264
    }
152
88
153
88
    // Custom lower lane accesses to expand out variable indices
154
176
    for (auto Op : {ISD::EXTRACT_VECTOR_ELT, ISD::INSERT_VECTOR_ELT}) {
155
176
      for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32})
156
704
        setOperationAction(Op, T, Custom);
157
176
      if (Subtarget->hasUnimplementedSIMD128())
158
80
        for (auto T : {MVT::v2i64, MVT::v2f64})
159
160
          setOperationAction(Op, T, Custom);
160
176
    }
161
88
162
88
    // There is no i64x2.mul instruction
163
88
    setOperationAction(ISD::MUL, MVT::v2i64, Expand);
164
88
165
88
    // There are no vector select instructions
166
264
    for (auto Op : {ISD::VSELECT, ISD::SELECT_CC, ISD::SELECT}) {
167
264
      for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32})
168
1.05k
        setOperationAction(Op, T, Expand);
169
264
      if (Subtarget->hasUnimplementedSIMD128())
170
120
        for (auto T : {MVT::v2i64, MVT::v2f64})
171
240
          setOperationAction(Op, T, Expand);
172
264
    }
173
88
174
88
    // Expand integer operations supported for scalars but not SIMD
175
88
    for (auto Op : {ISD::CTLZ, ISD::CTTZ, ISD::CTPOP, ISD::SDIV, ISD::UDIV,
176
792
                    ISD::SREM, ISD::UREM, ISD::ROTL, ISD::ROTR}) {
177
792
      for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
178
2.37k
        setOperationAction(Op, T, Expand);
179
792
      if (Subtarget->hasUnimplementedSIMD128())
180
360
        setOperationAction(Op, MVT::v2i64, Expand);
181
792
    }
182
88
183
88
    // Expand float operations supported for scalars but not SIMD
184
88
    for (auto Op : {ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FNEARBYINT,
185
88
                    ISD::FCOPYSIGN, ISD::FLOG, ISD::FLOG2, ISD::FLOG10,
186
968
                    ISD::FEXP, ISD::FEXP2, ISD::FRINT}) {
187
968
      setOperationAction(Op, MVT::v4f32, Expand);
188
968
      if (Subtarget->hasUnimplementedSIMD128())
189
440
        setOperationAction(Op, MVT::v2f64, Expand);
190
968
    }
191
88
192
88
    // Expand additional SIMD ops that V8 hasn't implemented yet
193
88
    if (!Subtarget->hasUnimplementedSIMD128()) {
194
48
      setOperationAction(ISD::FSQRT, MVT::v4f32, Expand);
195
48
      setOperationAction(ISD::FDIV, MVT::v4f32, Expand);
196
48
    }
197
88
  }
198
546
199
546
  // As a special case, these operators use the type to mean the type to
200
546
  // sign-extend from.
201
546
  setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
202
546
  if (!Subtarget->hasSignExt()) {
203
506
    // Sign extends are legal only when extending a vector extract
204
506
    auto Action = Subtarget->hasSIMD128() ? 
Custom66
:
Expand440
;
205
506
    for (auto T : {MVT::i8, MVT::i16, MVT::i32})
206
1.51k
      setOperationAction(ISD::SIGN_EXTEND_INREG, T, Action);
207
506
  }
208
546
  for (auto T : MVT::integer_vector_valuetypes())
209
42.5k
    setOperationAction(ISD::SIGN_EXTEND_INREG, T, Expand);
210
546
211
546
  // Dynamic stack allocation: use the default expansion.
212
546
  setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
213
546
  setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
214
546
  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVTPtr, Expand);
215
546
216
546
  setOperationAction(ISD::FrameIndex, MVT::i32, Custom);
217
546
  setOperationAction(ISD::CopyToReg, MVT::Other, Custom);
218
546
219
546
  // Expand these forms; we pattern-match the forms that we can handle in isel.
220
546
  for (auto T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
221
2.18k
    for (auto Op : {ISD::BR_CC, ISD::SELECT_CC})
222
4.36k
      setOperationAction(Op, T, Expand);
223
546
224
546
  // We have custom switch handling.
225
546
  setOperationAction(ISD::BR_JT, MVT::Other, Custom);
226
546
227
546
  // WebAssembly doesn't have:
228
546
  //  - Floating-point extending loads.
229
546
  //  - Floating-point truncating stores.
230
546
  //  - i1 extending loads.
231
546
  //  - extending/truncating SIMD loads/stores
232
546
  setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);
233
546
  setTruncStoreAction(MVT::f64, MVT::f32, Expand);
234
546
  for (auto T : MVT::integer_valuetypes())
235
3.27k
    for (auto Ext : {ISD::EXTLOAD, ISD::ZEXTLOAD, ISD::SEXTLOAD})
236
9.82k
      setLoadExtAction(Ext, T, MVT::i1, Promote);
237
546
  if (Subtarget->hasSIMD128()) {
238
88
    for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v4f32,
239
528
                   MVT::v2f64}) {
240
58.6k
      for (auto MemT : MVT::vector_valuetypes()) {
241
58.6k
        if (MVT(T) != MemT) {
242
58.0k
          setTruncStoreAction(T, MemT, Expand);
243
58.0k
          for (auto Ext : {ISD::EXTLOAD, ISD::ZEXTLOAD, ISD::SEXTLOAD})
244
174k
            setLoadExtAction(Ext, T, MemT, Expand);
245
58.0k
        }
246
58.6k
      }
247
528
    }
248
88
  }
249
546
250
546
  // Don't do anything clever with build_pairs
251
546
  setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
252
546
253
546
  // Trap lowers to wasm unreachable
254
546
  setOperationAction(ISD::TRAP, MVT::Other, Legal);
255
546
256
546
  // Exception handling intrinsics
257
546
  setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
258
546
  setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
259
546
260
546
  setMaxAtomicSizeInBitsSupported(64);
261
546
262
546
  if (Subtarget->hasBulkMemory()) {
263
26
    // Use memory.copy and friends over multiple loads and stores
264
26
    MaxStoresPerMemcpy = 1;
265
26
    MaxStoresPerMemcpyOptSize = 1;
266
26
    MaxStoresPerMemmove = 1;
267
26
    MaxStoresPerMemmoveOptSize = 1;
268
26
    MaxStoresPerMemset = 1;
269
26
    MaxStoresPerMemsetOptSize = 1;
270
26
  }
271
546
272
546
  // Override the __gnu_f2h_ieee/__gnu_h2f_ieee names so that the f32 name is
273
546
  // consistent with the f64 and f128 names.
274
546
  setLibcallName(RTLIB::FPEXT_F16_F32, "__extendhfsf2");
275
546
  setLibcallName(RTLIB::FPROUND_F32_F16, "__truncsfhf2");
276
546
277
546
  // Define the emscripten name for return address helper.
278
546
  // TODO: when implementing other WASM backends, make this generic or only do
279
546
  // this on emscripten depending on what they end up doing.
280
546
  setLibcallName(RTLIB::RETURN_ADDRESS, "emscripten_return_address");
281
546
282
546
  // Always convert switches to br_tables unless there is only one case, which
283
546
  // is equivalent to a simple branch. This reduces code size for wasm, and we
284
546
  // defer possible jump table optimizations to the VM.
285
546
  setMinimumJumpTableEntries(2);
286
546
}
287
288
TargetLowering::AtomicExpansionKind
289
134
WebAssemblyTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
290
134
  // We have wasm instructions for these
291
134
  switch (AI->getOperation()) {
292
134
  case AtomicRMWInst::Add:
293
110
  case AtomicRMWInst::Sub:
294
110
  case AtomicRMWInst::And:
295
110
  case AtomicRMWInst::Or:
296
110
  case AtomicRMWInst::Xor:
297
110
  case AtomicRMWInst::Xchg:
298
110
    return AtomicExpansionKind::None;
299
110
  default:
300
24
    break;
301
24
  }
302
24
  return AtomicExpansionKind::CmpXChg;
303
24
}
304
305
FastISel *WebAssemblyTargetLowering::createFastISel(
306
666
    FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo) const {
307
666
  return WebAssembly::createFastISel(FuncInfo, LibInfo);
308
666
}
309
310
MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
311
7.99k
                                                      EVT VT) const {
312
7.99k
  unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1);
313
7.99k
  if (BitWidth > 1 && BitWidth < 8)
314
1
    BitWidth = 8;
315
7.99k
316
7.99k
  if (BitWidth > 64) {
317
111
    // The shift will be lowered to a libcall, and compiler-rt libcalls expect
318
111
    // the count to be an i32.
319
111
    BitWidth = 32;
320
111
    assert(BitWidth >= Log2_32_Ceil(VT.getSizeInBits()) &&
321
111
           "32-bit shift counts ought to be enough for anyone");
322
111
  }
323
7.99k
324
7.99k
  MVT Result = MVT::getIntegerVT(BitWidth);
325
7.99k
  assert(Result != MVT::INVALID_SIMPLE_VALUE_TYPE &&
326
7.99k
         "Unable to represent scalar shift amount type");
327
7.99k
  return Result;
328
7.99k
}
329
330
// Lower an fp-to-int conversion operator from the LLVM opcode, which has an
331
// undefined result on invalid/overflow, to the WebAssembly opcode, which
332
// traps on invalid/overflow.
333
static MachineBasicBlock *LowerFPToInt(MachineInstr &MI, DebugLoc DL,
334
                                       MachineBasicBlock *BB,
335
                                       const TargetInstrInfo &TII,
336
                                       bool IsUnsigned, bool Int64,
337
26
                                       bool Float64, unsigned LoweredOpcode) {
338
26
  MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
339
26
340
26
  unsigned OutReg = MI.getOperand(0).getReg();
341
26
  unsigned InReg = MI.getOperand(1).getReg();
342
26
343
26
  unsigned Abs = Float64 ? 
WebAssembly::ABS_F6412
:
WebAssembly::ABS_F3214
;
344
26
  unsigned FConst = Float64 ? 
WebAssembly::CONST_F6412
:
WebAssembly::CONST_F3214
;
345
26
  unsigned LT = Float64 ? 
WebAssembly::LT_F6412
:
WebAssembly::LT_F3214
;
346
26
  unsigned GE = Float64 ? 
WebAssembly::GE_F6412
:
WebAssembly::GE_F3214
;
347
26
  unsigned IConst = Int64 ? 
WebAssembly::CONST_I6412
:
WebAssembly::CONST_I3214
;
348
26
  unsigned Eqz = WebAssembly::EQZ_I32;
349
26
  unsigned And = WebAssembly::AND_I32;
350
26
  int64_t Limit = Int64 ? INT64_MIN : INT32_MIN;
351
26
  int64_t Substitute = IsUnsigned ? 
014
:
Limit12
;
352
26
  double CmpVal = IsUnsigned ? 
-(double)Limit * 2.014
:
-(double)Limit12
;
353
26
  auto &Context = BB->getParent()->getFunction().getContext();
354
26
  Type *Ty = Float64 ? 
Type::getDoubleTy(Context)12
:
Type::getFloatTy(Context)14
;
355
26
356
26
  const BasicBlock *LLVMBB = BB->getBasicBlock();
357
26
  MachineFunction *F = BB->getParent();
358
26
  MachineBasicBlock *TrueMBB = F->CreateMachineBasicBlock(LLVMBB);
359
26
  MachineBasicBlock *FalseMBB = F->CreateMachineBasicBlock(LLVMBB);
360
26
  MachineBasicBlock *DoneMBB = F->CreateMachineBasicBlock(LLVMBB);
361
26
362
26
  MachineFunction::iterator It = ++BB->getIterator();
363
26
  F->insert(It, FalseMBB);
364
26
  F->insert(It, TrueMBB);
365
26
  F->insert(It, DoneMBB);
366
26
367
26
  // Transfer the remainder of BB and its successor edges to DoneMBB.
368
26
  DoneMBB->splice(DoneMBB->begin(), BB, std::next(MI.getIterator()), BB->end());
369
26
  DoneMBB->transferSuccessorsAndUpdatePHIs(BB);
370
26
371
26
  BB->addSuccessor(TrueMBB);
372
26
  BB->addSuccessor(FalseMBB);
373
26
  TrueMBB->addSuccessor(DoneMBB);
374
26
  FalseMBB->addSuccessor(DoneMBB);
375
26
376
26
  unsigned Tmp0, Tmp1, CmpReg, EqzReg, FalseReg, TrueReg;
377
26
  Tmp0 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
378
26
  Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
379
26
  CmpReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
380
26
  EqzReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
381
26
  FalseReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
382
26
  TrueReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
383
26
384
26
  MI.eraseFromParent();
385
26
  // For signed numbers, we can do a single comparison to determine whether
386
26
  // fabs(x) is within range.
387
26
  if (IsUnsigned) {
388
14
    Tmp0 = InReg;
389
14
  } else {
390
12
    BuildMI(BB, DL, TII.get(Abs), Tmp0).addReg(InReg);
391
12
  }
392
26
  BuildMI(BB, DL, TII.get(FConst), Tmp1)
393
26
      .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, CmpVal)));
394
26
  BuildMI(BB, DL, TII.get(LT), CmpReg).addReg(Tmp0).addReg(Tmp1);
395
26
396
26
  // For unsigned numbers, we have to do a separate comparison with zero.
397
26
  if (IsUnsigned) {
398
14
    Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
399
14
    unsigned SecondCmpReg =
400
14
        MRI.createVirtualRegister(&WebAssembly::I32RegClass);
401
14
    unsigned AndReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
402
14
    BuildMI(BB, DL, TII.get(FConst), Tmp1)
403
14
        .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, 0.0)));
404
14
    BuildMI(BB, DL, TII.get(GE), SecondCmpReg).addReg(Tmp0).addReg(Tmp1);
405
14
    BuildMI(BB, DL, TII.get(And), AndReg).addReg(CmpReg).addReg(SecondCmpReg);
406
14
    CmpReg = AndReg;
407
14
  }
408
26
409
26
  BuildMI(BB, DL, TII.get(Eqz), EqzReg).addReg(CmpReg);
410
26
411
26
  // Create the CFG diamond to select between doing the conversion or using
412
26
  // the substitute value.
413
26
  BuildMI(BB, DL, TII.get(WebAssembly::BR_IF)).addMBB(TrueMBB).addReg(EqzReg);
414
26
  BuildMI(FalseMBB, DL, TII.get(LoweredOpcode), FalseReg).addReg(InReg);
415
26
  BuildMI(FalseMBB, DL, TII.get(WebAssembly::BR)).addMBB(DoneMBB);
416
26
  BuildMI(TrueMBB, DL, TII.get(IConst), TrueReg).addImm(Substitute);
417
26
  BuildMI(*DoneMBB, DoneMBB->begin(), DL, TII.get(TargetOpcode::PHI), OutReg)
418
26
      .addReg(FalseReg)
419
26
      .addMBB(FalseMBB)
420
26
      .addReg(TrueReg)
421
26
      .addMBB(TrueMBB);
422
26
423
26
  return DoneMBB;
424
26
}
425
426
MachineBasicBlock *WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
427
26
    MachineInstr &MI, MachineBasicBlock *BB) const {
428
26
  const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
429
26
  DebugLoc DL = MI.getDebugLoc();
430
26
431
26
  switch (MI.getOpcode()) {
432
26
  default:
433
0
    llvm_unreachable("Unexpected instr type to insert");
434
26
  case WebAssembly::FP_TO_SINT_I32_F32:
435
5
    return LowerFPToInt(MI, DL, BB, TII, false, false, false,
436
5
                        WebAssembly::I32_TRUNC_S_F32);
437
26
  case WebAssembly::FP_TO_UINT_I32_F32:
438
7
    return LowerFPToInt(MI, DL, BB, TII, true, false, false,
439
7
                        WebAssembly::I32_TRUNC_U_F32);
440
26
  case WebAssembly::FP_TO_SINT_I64_F32:
441
1
    return LowerFPToInt(MI, DL, BB, TII, false, true, false,
442
1
                        WebAssembly::I64_TRUNC_S_F32);
443
26
  case WebAssembly::FP_TO_UINT_I64_F32:
444
1
    return LowerFPToInt(MI, DL, BB, TII, true, true, false,
445
1
                        WebAssembly::I64_TRUNC_U_F32);
446
26
  case WebAssembly::FP_TO_SINT_I32_F64:
447
1
    return LowerFPToInt(MI, DL, BB, TII, false, false, true,
448
1
                        WebAssembly::I32_TRUNC_S_F64);
449
26
  case WebAssembly::FP_TO_UINT_I32_F64:
450
1
    return LowerFPToInt(MI, DL, BB, TII, true, false, true,
451
1
                        WebAssembly::I32_TRUNC_U_F64);
452
26
  case WebAssembly::FP_TO_SINT_I64_F64:
453
5
    return LowerFPToInt(MI, DL, BB, TII, false, true, true,
454
5
                        WebAssembly::I64_TRUNC_S_F64);
455
26
  case WebAssembly::FP_TO_UINT_I64_F64:
456
5
    return LowerFPToInt(MI, DL, BB, TII, true, true, true,
457
5
                        WebAssembly::I64_TRUNC_U_F64);
458
26
    llvm_unreachable("Unexpected instruction to emit with custom inserter");
459
26
  }
460
26
}
461
462
const char *
463
3
WebAssemblyTargetLowering::getTargetNodeName(unsigned Opcode) const {
464
3
  switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) {
465
3
  case WebAssemblyISD::FIRST_NUMBER:
466
0
    break;
467
3
#define HANDLE_NODETYPE(NODE)                                                  \
468
3
  case WebAssemblyISD::NODE:                                                   \
469
3
    return "WebAssemblyISD::" #NODE;
470
3
#include 
"WebAssemblyISD.def"0
471
3
#undef HANDLE_NODETYPE
472
3
  }
473
3
  
return nullptr0
;
474
3
}
475
476
std::pair<unsigned, const TargetRegisterClass *>
477
WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
478
36
    const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
479
36
  // First, see if this is a constraint that directly corresponds to a
480
36
  // WebAssembly register class.
481
36
  if (Constraint.size() == 1) {
482
22
    switch (Constraint[0]) {
483
22
    case 'r':
484
16
      assert(VT != MVT::iPTR && "Pointer MVT not expected here");
485
16
      if (Subtarget->hasSIMD128() && 
VT.isVector()0
) {
486
0
        if (VT.getSizeInBits() == 128)
487
0
          return std::make_pair(0U, &WebAssembly::V128RegClass);
488
16
      }
489
16
      if (VT.isInteger() && !VT.isVector()) {
490
16
        if (VT.getSizeInBits() <= 32)
491
14
          return std::make_pair(0U, &WebAssembly::I32RegClass);
492
2
        if (VT.getSizeInBits() <= 64)
493
2
          return std::make_pair(0U, &WebAssembly::I64RegClass);
494
0
      }
495
0
      break;
496
6
    default:
497
6
      break;
498
20
    }
499
20
  }
500
20
501
20
  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
502
20
}
503
504
7
bool WebAssemblyTargetLowering::isCheapToSpeculateCttz() const {
505
7
  // Assume ctz is a relatively cheap operation.
506
7
  return true;
507
7
}
508
509
7
bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz() const {
510
7
  // Assume clz is a relatively cheap operation.
511
7
  return true;
512
7
}
513
514
bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
515
                                                      const AddrMode &AM,
516
                                                      Type *Ty, unsigned AS,
517
6.63k
                                                      Instruction *I) const {
518
6.63k
  // WebAssembly offsets are added as unsigned without wrapping. The
519
6.63k
  // isLegalAddressingMode gives us no way to determine if wrapping could be
520
6.63k
  // happening, so we approximate this by accepting only non-negative offsets.
521
6.63k
  if (AM.BaseOffs < 0)
522
228
    return false;
523
6.40k
524
6.40k
  // WebAssembly has no scale register operands.
525
6.40k
  if (AM.Scale != 0)
526
230
    return false;
527
6.17k
528
6.17k
  // Everything else is legal.
529
6.17k
  return true;
530
6.17k
}
531
532
bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses(
533
    EVT /*VT*/, unsigned /*AddrSpace*/, unsigned /*Align*/,
534
144
    MachineMemOperand::Flags /*Flags*/, bool *Fast) const {
535
144
  // WebAssembly supports unaligned accesses, though it should be declared
536
144
  // with the p2align attribute on loads and stores which do so, and there
537
144
  // may be a performance impact. We tell LLVM they're "fast" because
538
144
  // for the kinds of things that LLVM uses this for (merging adjacent stores
539
144
  // of constants, etc.), WebAssembly implementations will either want the
540
144
  // unaligned access or they'll split anyway.
541
144
  if (Fast)
542
3
    *Fast = true;
543
144
  return true;
544
144
}
545
546
bool WebAssemblyTargetLowering::isIntDivCheap(EVT VT,
547
25
                                              AttributeList Attr) const {
548
25
  // The current thinking is that wasm engines will perform this optimization,
549
25
  // so we can save on code size.
550
25
  return true;
551
25
}
552
553
EVT WebAssemblyTargetLowering::getSetCCResultType(const DataLayout &DL,
554
                                                  LLVMContext &C,
555
3.89k
                                                  EVT VT) const {
556
3.89k
  if (VT.isVector())
557
482
    return VT.changeVectorElementTypeToInteger();
558
3.41k
559
3.41k
  return TargetLowering::getSetCCResultType(DL, C, VT);
560
3.41k
}
561
562
bool WebAssemblyTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
563
                                                   const CallInst &I,
564
                                                   MachineFunction &MF,
565
208
                                                   unsigned Intrinsic) const {
566
208
  switch (Intrinsic) {
567
208
  case Intrinsic::wasm_atomic_notify:
568
8
    Info.opc = ISD::INTRINSIC_W_CHAIN;
569
8
    Info.memVT = MVT::i32;
570
8
    Info.ptrVal = I.getArgOperand(0);
571
8
    Info.offset = 0;
572
8
    Info.align = 4;
573
8
    // atomic.notify instruction does not really load the memory specified with
574
8
    // this argument, but MachineMemOperand should either be load or store, so
575
8
    // we set this to a load.
576
8
    // FIXME Volatile isn't really correct, but currently all LLVM atomic
577
8
    // instructions are treated as volatiles in the backend, so we should be
578
8
    // consistent. The same applies for wasm_atomic_wait intrinsics too.
579
8
    Info.flags = MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad;
580
8
    return true;
581
208
  case Intrinsic::wasm_atomic_wait_i32:
582
9
    Info.opc = ISD::INTRINSIC_W_CHAIN;
583
9
    Info.memVT = MVT::i32;
584
9
    Info.ptrVal = I.getArgOperand(0);
585
9
    Info.offset = 0;
586
9
    Info.align = 4;
587
9
    Info.flags = MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad;
588
9
    return true;
589
208
  case Intrinsic::wasm_atomic_wait_i64:
590
6
    Info.opc = ISD::INTRINSIC_W_CHAIN;
591
6
    Info.memVT = MVT::i64;
592
6
    Info.ptrVal = I.getArgOperand(0);
593
6
    Info.offset = 0;
594
6
    Info.align = 8;
595
6
    Info.flags = MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad;
596
6
    return true;
597
208
  default:
598
185
    return false;
599
208
  }
600
208
}
601
602
//===----------------------------------------------------------------------===//
603
// WebAssembly Lowering private implementation.
604
//===----------------------------------------------------------------------===//
605
606
//===----------------------------------------------------------------------===//
607
// Lowering Code
608
//===----------------------------------------------------------------------===//
609
610
2
static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *Msg) {
611
2
  MachineFunction &MF = DAG.getMachineFunction();
612
2
  DAG.getContext()->diagnose(
613
2
      DiagnosticInfoUnsupported(MF.getFunction(), Msg, DL.getDebugLoc()));
614
2
}
615
616
// Test whether the given calling convention is supported.
617
8.73k
static bool callingConvSupported(CallingConv::ID CallConv) {
618
8.73k
  // We currently support the language-independent target-independent
619
8.73k
  // conventions. We don't yet have a way to annotate calls with properties like
620
8.73k
  // "cold", and we don't have any call-clobbered registers, so these are mostly
621
8.73k
  // all handled the same.
622
8.73k
  return CallConv == CallingConv::C || 
CallConv == CallingConv::Fast4
||
623
8.73k
         
CallConv == CallingConv::Cold2
||
624
8.73k
         
CallConv == CallingConv::PreserveMost0
||
625
8.73k
         
CallConv == CallingConv::PreserveAll0
||
626
8.73k
         
CallConv == CallingConv::CXX_FAST_TLS0
;
627
8.73k
}
628
629
SDValue
630
WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
631
860
                                     SmallVectorImpl<SDValue> &InVals) const {
632
860
  SelectionDAG &DAG = CLI.DAG;
633
860
  SDLoc DL = CLI.DL;
634
860
  SDValue Chain = CLI.Chain;
635
860
  SDValue Callee = CLI.Callee;
636
860
  MachineFunction &MF = DAG.getMachineFunction();
637
860
  auto Layout = MF.getDataLayout();
638
860
639
860
  CallingConv::ID CallConv = CLI.CallConv;
640
860
  if (!callingConvSupported(CallConv))
641
0
    fail(DL, DAG,
642
0
         "WebAssembly doesn't support language-specific or target-specific "
643
0
         "calling conventions yet");
644
860
  if (CLI.IsPatchPoint)
645
0
    fail(DL, DAG, "WebAssembly doesn't support patch point yet");
646
860
647
860
  // Fail if tail calls are required but not enabled
648
860
  if (!Subtarget->hasTailCall()) {
649
812
    if ((CallConv == CallingConv::Fast && 
CLI.IsTailCall1
&&
650
812
         
MF.getTarget().Options.GuaranteedTailCallOpt1
) ||
651
812
        (CLI.CS && 
CLI.CS.isMustTailCall()586
))
652
0
      fail(DL, DAG, "WebAssembly 'tail-call' feature not enabled");
653
812
    CLI.IsTailCall = false;
654
812
  }
655
860
656
860
  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
657
860
  if (Ins.size() > 1)
658
0
    fail(DL, DAG, "WebAssembly doesn't support more than 1 returned value yet");
659
860
660
860
  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
661
860
  SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
662
860
  unsigned NumFixedArgs = 0;
663
1.87k
  for (unsigned I = 0; I < Outs.size(); 
++I1.01k
) {
664
1.01k
    const ISD::OutputArg &Out = Outs[I];
665
1.01k
    SDValue &OutVal = OutVals[I];
666
1.01k
    if (Out.Flags.isNest())
667
0
      fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
668
1.01k
    if (Out.Flags.isInAlloca())
669
0
      fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
670
1.01k
    if (Out.Flags.isInConsecutiveRegs())
671
0
      fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
672
1.01k
    if (Out.Flags.isInConsecutiveRegsLast())
673
0
      fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
674
1.01k
    if (Out.Flags.isByVal() && 
Out.Flags.getByValSize() != 013
) {
675
10
      auto &MFI = MF.getFrameInfo();
676
10
      int FI = MFI.CreateStackObject(Out.Flags.getByValSize(),
677
10
                                     Out.Flags.getByValAlign(),
678
10
                                     /*isSS=*/false);
679
10
      SDValue SizeNode =
680
10
          DAG.getConstant(Out.Flags.getByValSize(), DL, MVT::i32);
681
10
      SDValue FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
682
10
      Chain = DAG.getMemcpy(
683
10
          Chain, DL, FINode, OutVal, SizeNode, Out.Flags.getByValAlign(),
684
10
          /*isVolatile*/ false, /*AlwaysInline=*/false,
685
10
          /*isTailCall*/ false, MachinePointerInfo(), MachinePointerInfo());
686
10
      OutVal = FINode;
687
10
    }
688
1.01k
    // Count the number of fixed args *after* legalization.
689
1.01k
    NumFixedArgs += Out.IsFixed;
690
1.01k
  }
691
860
692
860
  bool IsVarArg = CLI.IsVarArg;
693
860
  auto PtrVT = getPointerTy(Layout);
694
860
695
860
  // Analyze operands of the call, assigning locations to each operand.
696
860
  SmallVector<CCValAssign, 16> ArgLocs;
697
860
  CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
698
860
699
860
  if (IsVarArg) {
700
17
    // Outgoing non-fixed arguments are placed in a buffer. First
701
17
    // compute their offsets and the total amount of buffer space needed.
702
40
    for (unsigned I = NumFixedArgs; I < Outs.size(); 
++I23
) {
703
23
      const ISD::OutputArg &Out = Outs[I];
704
23
      SDValue &Arg = OutVals[I];
705
23
      EVT VT = Arg.getValueType();
706
23
      assert(VT != MVT::iPTR && "Legalized args should be concrete");
707
23
      Type *Ty = VT.getTypeForEVT(*DAG.getContext());
708
23
      unsigned Align = std::max(Out.Flags.getOrigAlign(),
709
23
                                Layout.getABITypeAlignment(Ty));
710
23
      unsigned Offset = CCInfo.AllocateStack(Layout.getTypeAllocSize(Ty),
711
23
                                             Align);
712
23
      CCInfo.addLoc(CCValAssign::getMem(ArgLocs.size(), VT.getSimpleVT(),
713
23
                                        Offset, VT.getSimpleVT(),
714
23
                                        CCValAssign::Full));
715
23
    }
716
17
  }
717
860
718
860
  unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
719
860
720
860
  SDValue FINode;
721
860
  if (IsVarArg && 
NumBytes17
) {
722
14
    // For non-fixed arguments, next emit stores to store the argument values
723
14
    // to the stack buffer at the offsets computed above.
724
14
    int FI = MF.getFrameInfo().CreateStackObject(NumBytes,
725
14
                                                 Layout.getStackAlignment(),
726
14
                                                 /*isSS=*/false);
727
14
    unsigned ValNo = 0;
728
14
    SmallVector<SDValue, 8> Chains;
729
14
    for (SDValue Arg :
730
23
         make_range(OutVals.begin() + NumFixedArgs, OutVals.end())) {
731
23
      assert(ArgLocs[ValNo].getValNo() == ValNo &&
732
23
             "ArgLocs should remain in order and only hold varargs args");
733
23
      unsigned Offset = ArgLocs[ValNo++].getLocMemOffset();
734
23
      FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
735
23
      SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, FINode,
736
23
                                DAG.getConstant(Offset, DL, PtrVT));
737
23
      Chains.push_back(
738
23
          DAG.getStore(Chain, DL, Arg, Add,
739
23
                       MachinePointerInfo::getFixedStack(MF, FI, Offset), 0));
740
23
    }
741
14
    if (!Chains.empty())
742
14
      Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
743
846
  } else if (IsVarArg) {
744
3
    FINode = DAG.getIntPtrConstant(0, DL);
745
3
  }
746
860
747
860
  if (Callee->getOpcode() == ISD::GlobalAddress) {
748
578
    // If the callee is a GlobalAddress node (quite common, every direct call
749
578
    // is) turn it into a TargetGlobalAddress node so that LowerGlobalAddress
750
578
    // doesn't at MO_GOT which is not needed for direct calls.
751
578
    GlobalAddressSDNode* GA = cast<GlobalAddressSDNode>(Callee);
752
578
    Callee = DAG.getTargetGlobalAddress(GA->getGlobal(), DL,
753
578
                                        getPointerTy(DAG.getDataLayout()),
754
578
                                        GA->getOffset());
755
578
    Callee = DAG.getNode(WebAssemblyISD::Wrapper, DL,
756
578
                         getPointerTy(DAG.getDataLayout()), Callee);
757
578
  }
758
860
759
860
  // Compute the operands for the CALLn node.
760
860
  SmallVector<SDValue, 16> Ops;
761
860
  Ops.push_back(Chain);
762
860
  Ops.push_back(Callee);
763
860
764
860
  // Add all fixed arguments. Note that for non-varargs calls, NumFixedArgs
765
860
  // isn't reliable.
766
860
  Ops.append(OutVals.begin(),
767
860
             IsVarArg ? 
OutVals.begin() + NumFixedArgs17
:
OutVals.end()843
);
768
860
  // Add a pointer to the vararg buffer.
769
860
  if (IsVarArg)
770
17
    Ops.push_back(FINode);
771
860
772
860
  SmallVector<EVT, 8> InTys;
773
860
  for (const auto &In : Ins) {
774
416
    assert(!In.Flags.isByVal() && "byval is not valid for return values");
775
416
    assert(!In.Flags.isNest() && "nest is not valid for return values");
776
416
    if (In.Flags.isInAlloca())
777
0
      fail(DL, DAG, "WebAssembly hasn't implemented inalloca return values");
778
416
    if (In.Flags.isInConsecutiveRegs())
779
0
      fail(DL, DAG, "WebAssembly hasn't implemented cons regs return values");
780
416
    if (In.Flags.isInConsecutiveRegsLast())
781
0
      fail(DL, DAG,
782
0
           "WebAssembly hasn't implemented cons regs last return values");
783
416
    // Ignore In.getOrigAlign() because all our arguments are passed in
784
416
    // registers.
785
416
    InTys.push_back(In.VT);
786
416
  }
787
860
788
860
  if (CLI.IsTailCall) {
789
21
    // ret_calls do not return values to the current frame
790
21
    SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
791
21
    return DAG.getNode(WebAssemblyISD::RET_CALL, DL, NodeTys, Ops);
792
21
  }
793
839
794
839
  InTys.push_back(MVT::Other);
795
839
  SDVTList InTyList = DAG.getVTList(InTys);
796
839
  SDValue Res =
797
839
      DAG.getNode(Ins.empty() ? 
WebAssemblyISD::CALL0438
:
WebAssemblyISD::CALL1401
,
798
839
                  DL, InTyList, Ops);
799
839
  if (Ins.empty()) {
800
438
    Chain = Res;
801
438
  } else {
802
401
    InVals.push_back(Res);
803
401
    Chain = Res.getValue(1);
804
401
  }
805
839
806
839
  return Chain;
807
839
}
808
809
bool WebAssemblyTargetLowering::CanLowerReturn(
810
    CallingConv::ID /*CallConv*/, MachineFunction & /*MF*/, bool /*IsVarArg*/,
811
    const SmallVectorImpl<ISD::OutputArg> &Outs,
812
5.34k
    LLVMContext & /*Context*/) const {
813
5.34k
  // WebAssembly can't currently handle returning tuples.
814
5.34k
  return Outs.size() <= 1;
815
5.34k
}
816
817
SDValue WebAssemblyTargetLowering::LowerReturn(
818
    SDValue Chain, CallingConv::ID CallConv, bool /*IsVarArg*/,
819
    const SmallVectorImpl<ISD::OutputArg> &Outs,
820
    const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
821
3.92k
    SelectionDAG &DAG) const {
822
3.92k
  assert(Outs.size() <= 1 && "WebAssembly can only return up to one value");
823
3.92k
  if (!callingConvSupported(CallConv))
824
0
    fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
825
3.92k
826
3.92k
  SmallVector<SDValue, 4> RetOps(1, Chain);
827
3.92k
  RetOps.append(OutVals.begin(), OutVals.end());
828
3.92k
  Chain = DAG.getNode(WebAssemblyISD::RETURN, DL, MVT::Other, RetOps);
829
3.92k
830
3.92k
  // Record the number and types of the return values.
831
3.92k
  for (const ISD::OutputArg &Out : Outs) {
832
2.42k
    assert(!Out.Flags.isByVal() && "byval is not valid for return values");
833
2.42k
    assert(!Out.Flags.isNest() && "nest is not valid for return values");
834
2.42k
    assert(Out.IsFixed && "non-fixed return value is not valid");
835
2.42k
    if (Out.Flags.isInAlloca())
836
0
      fail(DL, DAG, "WebAssembly hasn't implemented inalloca results");
837
2.42k
    if (Out.Flags.isInConsecutiveRegs())
838
0
      fail(DL, DAG, "WebAssembly hasn't implemented cons regs results");
839
2.42k
    if (Out.Flags.isInConsecutiveRegsLast())
840
0
      fail(DL, DAG, "WebAssembly hasn't implemented cons regs last results");
841
2.42k
  }
842
3.92k
843
3.92k
  return Chain;
844
3.92k
}
845
846
SDValue WebAssemblyTargetLowering::LowerFormalArguments(
847
    SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
848
    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
849
3.95k
    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
850
3.95k
  if (!callingConvSupported(CallConv))
851
0
    fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
852
3.95k
853
3.95k
  MachineFunction &MF = DAG.getMachineFunction();
854
3.95k
  auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
855
3.95k
856
3.95k
  // Set up the incoming ARGUMENTS value, which serves to represent the liveness
857
3.95k
  // of the incoming values before they're represented by virtual registers.
858
3.95k
  MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
859
3.95k
860
10.7k
  for (const ISD::InputArg &In : Ins) {
861
10.7k
    if (In.Flags.isInAlloca())
862
0
      fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
863
10.7k
    if (In.Flags.isNest())
864
0
      fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
865
10.7k
    if (In.Flags.isInConsecutiveRegs())
866
0
      fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
867
10.7k
    if (In.Flags.isInConsecutiveRegsLast())
868
0
      fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
869
10.7k
    // Ignore In.getOrigAlign() because all our arguments are passed in
870
10.7k
    // registers.
871
10.7k
    InVals.push_back(In.Used ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
872
10.6k
                                           DAG.getTargetConstant(InVals.size(),
873
10.6k
                                                                 DL, MVT::i32))
874
10.7k
                             : 
DAG.getUNDEF(In.VT)101
);
875
10.7k
876
10.7k
    // Record the number and types of arguments.
877
10.7k
    MFI->addParam(In.VT);
878
10.7k
  }
879
3.95k
880
3.95k
  // Varargs are copied into a buffer allocated by the caller, and a pointer to
881
3.95k
  // the buffer is passed as an argument.
882
3.95k
  if (IsVarArg) {
883
6
    MVT PtrVT = getPointerTy(MF.getDataLayout());
884
6
    unsigned VarargVreg =
885
6
        MF.getRegInfo().createVirtualRegister(getRegClassFor(PtrVT));
886
6
    MFI->setVarargBufferVreg(VarargVreg);
887
6
    Chain = DAG.getCopyToReg(
888
6
        Chain, DL, VarargVreg,
889
6
        DAG.getNode(WebAssemblyISD::ARGUMENT, DL, PtrVT,
890
6
                    DAG.getTargetConstant(Ins.size(), DL, MVT::i32)));
891
6
    MFI->addParam(PtrVT);
892
6
  }
893
3.95k
894
3.95k
  // Record the number and types of arguments and results.
895
3.95k
  SmallVector<MVT, 4> Params;
896
3.95k
  SmallVector<MVT, 4> Results;
897
3.95k
  computeSignatureVTs(MF.getFunction().getFunctionType(), MF.getFunction(),
898
3.95k
                      DAG.getTarget(), Params, Results);
899
3.95k
  for (MVT VT : Results)
900
2.43k
    MFI->addResult(VT);
901
3.95k
  // TODO: Use signatures in WebAssemblyMachineFunctionInfo too and unify
902
3.95k
  // the param logic here with ComputeSignatureVTs
903
3.95k
  assert(MFI->getParams().size() == Params.size() &&
904
3.95k
         std::equal(MFI->getParams().begin(), MFI->getParams().end(),
905
3.95k
                    Params.begin()));
906
3.95k
907
3.95k
  return Chain;
908
3.95k
}
909
910
void WebAssemblyTargetLowering::ReplaceNodeResults(
911
1
    SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const {
912
1
  switch (N->getOpcode()) {
913
1
  case ISD::SIGN_EXTEND_INREG:
914
1
    // Do not add any results, signifying that N should not be custom lowered
915
1
    // after all. This happens because simd128 turns on custom lowering for
916
1
    // SIGN_EXTEND_INREG, but for non-vector sign extends the result might be an
917
1
    // illegal type.
918
1
    break;
919
1
  default:
920
0
    llvm_unreachable(
921
1
        "ReplaceNodeResults not implemented for this op for WebAssembly!");
922
1
  }
923
1
}
924
925
//===----------------------------------------------------------------------===//
926
//  Custom lowering hooks.
927
//===----------------------------------------------------------------------===//
928
929
SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
930
15.7k
                                                  SelectionDAG &DAG) const {
931
15.7k
  SDLoc DL(Op);
932
15.7k
  switch (Op.getOpcode()) {
933
15.7k
  default:
934
0
    llvm_unreachable("unimplemented operation lowering");
935
15.7k
    
return SDValue()0
;
936
15.7k
  case ISD::FrameIndex:
937
251
    return LowerFrameIndex(Op, DAG);
938
15.7k
  case ISD::GlobalAddress:
939
532
    return LowerGlobalAddress(Op, DAG);
940
15.7k
  case ISD::ExternalSymbol:
941
109
    return LowerExternalSymbol(Op, DAG);
942
15.7k
  case ISD::JumpTable:
943
0
    return LowerJumpTable(Op, DAG);
944
15.7k
  case ISD::BR_JT:
945
7
    return LowerBR_JT(Op, DAG);
946
15.7k
  case ISD::VASTART:
947
2
    return LowerVASTART(Op, DAG);
948
15.7k
  case ISD::BlockAddress:
949
0
  case ISD::BRIND:
950
0
    fail(DL, DAG, "WebAssembly hasn't implemented computed gotos");
951
0
    return SDValue();
952
3
  case ISD::RETURNADDR:
953
3
    return LowerRETURNADDR(Op, DAG);
954
4
  case ISD::FRAMEADDR:
955
4
    return LowerFRAMEADDR(Op, DAG);
956
5.01k
  case ISD::CopyToReg:
957
5.01k
    return LowerCopyToReg(Op, DAG);
958
6.96k
  case ISD::EXTRACT_VECTOR_ELT:
959
6.96k
  case ISD::INSERT_VECTOR_ELT:
960
6.96k
    return LowerAccessVectorElement(Op, DAG);
961
6.96k
  case ISD::INTRINSIC_VOID:
962
226
  case ISD::INTRINSIC_WO_CHAIN:
963
226
  case ISD::INTRINSIC_W_CHAIN:
964
226
    return LowerIntrinsic(Op, DAG);
965
612
  case ISD::SIGN_EXTEND_INREG:
966
612
    return LowerSIGN_EXTEND_INREG(Op, DAG);
967
1.50k
  case ISD::BUILD_VECTOR:
968
1.50k
    return LowerBUILD_VECTOR(Op, DAG);
969
226
  case ISD::VECTOR_SHUFFLE:
970
21
    return LowerVECTOR_SHUFFLE(Op, DAG);
971
457
  case ISD::SHL:
972
457
  case ISD::SRA:
973
457
  case ISD::SRL:
974
457
    return LowerShift(Op, DAG);
975
15.7k
  }
976
15.7k
}
977
978
SDValue WebAssemblyTargetLowering::LowerCopyToReg(SDValue Op,
979
5.01k
                                                  SelectionDAG &DAG) const {
980
5.01k
  SDValue Src = Op.getOperand(2);
981
5.01k
  if (isa<FrameIndexSDNode>(Src.getNode())) {
982
2
    // CopyToReg nodes don't support FrameIndex operands. Other targets select
983
2
    // the FI to some LEA-like instruction, but since we don't have that, we
984
2
    // need to insert some kind of instruction that can take an FI operand and
985
2
    // produces a value usable by CopyToReg (i.e. in a vreg). So insert a dummy
986
2
    // local.copy between Op and its FI operand.
987
2
    SDValue Chain = Op.getOperand(0);
988
2
    SDLoc DL(Op);
989
2
    unsigned Reg = cast<RegisterSDNode>(Op.getOperand(1))->getReg();
990
2
    EVT VT = Src.getValueType();
991
2
    SDValue Copy(DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32
992
2
                                                   : 
WebAssembly::COPY_I640
,
993
2
                                    DL, VT, Src),
994
2
                 0);
995
2
    return Op.getNode()->getNumValues() == 1
996
2
               ? 
DAG.getCopyToReg(Chain, DL, Reg, Copy)1
997
2
               : DAG.getCopyToReg(Chain, DL, Reg, Copy,
998
1
                                  Op.getNumOperands() == 4 ? 
Op.getOperand(3)0
999
1
                                                           : SDValue());
1000
2
  }
1001
5.00k
  return SDValue();
1002
5.00k
}
1003
1004
SDValue WebAssemblyTargetLowering::LowerFrameIndex(SDValue Op,
1005
251
                                                   SelectionDAG &DAG) const {
1006
251
  int FI = cast<FrameIndexSDNode>(Op)->getIndex();
1007
251
  return DAG.getTargetFrameIndex(FI, Op.getValueType());
1008
251
}
1009
1010
SDValue WebAssemblyTargetLowering::LowerRETURNADDR(SDValue Op,
1011
3
                                                   SelectionDAG &DAG) const {
1012
3
  SDLoc DL(Op);
1013
3
1014
3
  if (!Subtarget->getTargetTriple().isOSEmscripten()) {
1015
2
    fail(DL, DAG,
1016
2
         "Non-Emscripten WebAssembly hasn't implemented "
1017
2
         "__builtin_return_address");
1018
2
    return SDValue();
1019
2
  }
1020
1
1021
1
  if (verifyReturnAddressArgumentIsConstant(Op, DAG))
1022
0
    return SDValue();
1023
1
1024
1
  unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
1025
1
  return makeLibCall(DAG, RTLIB::RETURN_ADDRESS, Op.getValueType(),
1026
1
                     {DAG.getConstant(Depth, DL, MVT::i32)}, false, DL)
1027
1
      .first;
1028
1
}
1029
1030
SDValue WebAssemblyTargetLowering::LowerFRAMEADDR(SDValue Op,
1031
4
                                                  SelectionDAG &DAG) const {
1032
4
  // Non-zero depths are not supported by WebAssembly currently. Use the
1033
4
  // legalizer's default expansion, which is to return 0 (what this function is
1034
4
  // documented to do).
1035
4
  if (Op.getConstantOperandVal(0) > 0)
1036
1
    return SDValue();
1037
3
1038
3
  DAG.getMachineFunction().getFrameInfo().setFrameAddressIsTaken(true);
1039
3
  EVT VT = Op.getValueType();
1040
3
  unsigned FP =
1041
3
      Subtarget->getRegisterInfo()->getFrameRegister(DAG.getMachineFunction());
1042
3
  return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), FP, VT);
1043
3
}
1044
1045
SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
1046
532
                                                      SelectionDAG &DAG) const {
1047
532
  SDLoc DL(Op);
1048
532
  const auto *GA = cast<GlobalAddressSDNode>(Op);
1049
532
  EVT VT = Op.getValueType();
1050
532
  assert(GA->getTargetFlags() == 0 &&
1051
532
         "Unexpected target flags on generic GlobalAddressSDNode");
1052
532
  if (GA->getAddressSpace() != 0)
1053
0
    fail(DL, DAG, "WebAssembly only expects the 0 address space");
1054
532
1055
532
  unsigned OperandFlags = 0;
1056
532
  if (isPositionIndependent()) {
1057
54
    const GlobalValue *GV = GA->getGlobal();
1058
54
    if (getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV)) {
1059
14
      MachineFunction &MF = DAG.getMachineFunction();
1060
14
      MVT PtrVT = getPointerTy(MF.getDataLayout());
1061
14
      const char *BaseName;
1062
14
      if (GV->getValueType()->isFunctionTy()) {
1063
3
        BaseName = MF.createExternalSymbolName("__table_base");
1064
3
        OperandFlags = WebAssemblyII::MO_TABLE_BASE_REL;
1065
3
      }
1066
11
      else {
1067
11
        BaseName = MF.createExternalSymbolName("__memory_base");
1068
11
        OperandFlags = WebAssemblyII::MO_MEMORY_BASE_REL;
1069
11
      }
1070
14
      SDValue BaseAddr =
1071
14
          DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT,
1072
14
                      DAG.getTargetExternalSymbol(BaseName, PtrVT));
1073
14
1074
14
      SDValue SymAddr = DAG.getNode(
1075
14
          WebAssemblyISD::WrapperPIC, DL, VT,
1076
14
          DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset(),
1077
14
                                     OperandFlags));
1078
14
1079
14
      return DAG.getNode(ISD::ADD, DL, VT, BaseAddr, SymAddr);
1080
40
    } else {
1081
40
      OperandFlags = WebAssemblyII::MO_GOT;
1082
40
    }
1083
54
  }
1084
532
1085
532
  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1086
518
                     DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT,
1087
518
                                                GA->getOffset(), OperandFlags));
1088
532
}
1089
1090
SDValue
1091
WebAssemblyTargetLowering::LowerExternalSymbol(SDValue Op,
1092
109
                                               SelectionDAG &DAG) const {
1093
109
  SDLoc DL(Op);
1094
109
  const auto *ES = cast<ExternalSymbolSDNode>(Op);
1095
109
  EVT VT = Op.getValueType();
1096
109
  assert(ES->getTargetFlags() == 0 &&
1097
109
         "Unexpected target flags on generic ExternalSymbolSDNode");
1098
109
  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1099
109
                     DAG.getTargetExternalSymbol(ES->getSymbol(), VT));
1100
109
}
1101
1102
SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op,
1103
0
                                                  SelectionDAG &DAG) const {
1104
0
  // There's no need for a Wrapper node because we always incorporate a jump
1105
0
  // table operand into a BR_TABLE instruction, rather than ever
1106
0
  // materializing it in a register.
1107
0
  const JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
1108
0
  return DAG.getTargetJumpTable(JT->getIndex(), Op.getValueType(),
1109
0
                                JT->getTargetFlags());
1110
0
}
1111
1112
SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op,
1113
7
                                              SelectionDAG &DAG) const {
1114
7
  SDLoc DL(Op);
1115
7
  SDValue Chain = Op.getOperand(0);
1116
7
  const auto *JT = cast<JumpTableSDNode>(Op.getOperand(1));
1117
7
  SDValue Index = Op.getOperand(2);
1118
7
  assert(JT->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");
1119
7
1120
7
  SmallVector<SDValue, 8> Ops;
1121
7
  Ops.push_back(Chain);
1122
7
  Ops.push_back(Index);
1123
7
1124
7
  MachineJumpTableInfo *MJTI = DAG.getMachineFunction().getJumpTableInfo();
1125
7
  const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs;
1126
7
1127
7
  // Add an operand for each case.
1128
7
  for (auto MBB : MBBs)
1129
68
    Ops.push_back(DAG.getBasicBlock(MBB));
1130
7
1131
7
  // TODO: For now, we just pick something arbitrary for a default case for now.
1132
7
  // We really want to sniff out the guard and put in the real default case (and
1133
7
  // delete the guard).
1134
7
  Ops.push_back(DAG.getBasicBlock(MBBs[0]));
1135
7
1136
7
  return DAG.getNode(WebAssemblyISD::BR_TABLE, DL, MVT::Other, Ops);
1137
7
}
1138
1139
SDValue WebAssemblyTargetLowering::LowerVASTART(SDValue Op,
1140
2
                                                SelectionDAG &DAG) const {
1141
2
  SDLoc DL(Op);
1142
2
  EVT PtrVT = getPointerTy(DAG.getMachineFunction().getDataLayout());
1143
2
1144
2
  auto *MFI = DAG.getMachineFunction().getInfo<WebAssemblyFunctionInfo>();
1145
2
  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
1146
2
1147
2
  SDValue ArgN = DAG.getCopyFromReg(DAG.getEntryNode(), DL,
1148
2
                                    MFI->getVarargBufferVreg(), PtrVT);
1149
2
  return DAG.getStore(Op.getOperand(0), DL, ArgN, Op.getOperand(1),
1150
2
                      MachinePointerInfo(SV), 0);
1151
2
}
1152
1153
SDValue WebAssemblyTargetLowering::LowerIntrinsic(SDValue Op,
1154
226
                                                  SelectionDAG &DAG) const {
1155
226
  MachineFunction &MF = DAG.getMachineFunction();
1156
226
  unsigned IntNo;
1157
226
  switch (Op.getOpcode()) {
1158
226
  case ISD::INTRINSIC_VOID:
1159
41
  case ISD::INTRINSIC_W_CHAIN:
1160
41
    IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
1161
41
    break;
1162
185
  case ISD::INTRINSIC_WO_CHAIN:
1163
185
    IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
1164
185
    break;
1165
41
  default:
1166
0
    llvm_unreachable("Invalid intrinsic");
1167
226
  }
1168
226
  SDLoc DL(Op);
1169
226
1170
226
  switch (IntNo) {
1171
226
  default:
1172
202
    return SDValue(); // Don't custom lower most intrinsics.
1173
226
1174
226
  case Intrinsic::wasm_lsda: {
1175
13
    EVT VT = Op.getValueType();
1176
13
    const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1177
13
    MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
1178
13
    auto &Context = MF.getMMI().getContext();
1179
13
    MCSymbol *S = Context.getOrCreateSymbol(Twine("GCC_except_table") +
1180
13
                                            Twine(MF.getFunctionNumber()));
1181
13
    return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
1182
13
                       DAG.getMCSymbol(S, PtrVT));
1183
226
  }
1184
226
1185
226
  case Intrinsic::wasm_throw: {
1186
11
    // We only support C++ exceptions for now
1187
11
    int Tag = cast<ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue();
1188
11
    if (Tag != CPP_EXCEPTION)
1189
11
      
llvm_unreachable0
("Invalid tag!");
1190
11
    const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1191
11
    MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
1192
11
    const char *SymName = MF.createExternalSymbolName("__cpp_exception");
1193
11
    SDValue SymNode = DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT,
1194
11
                                  DAG.getTargetExternalSymbol(SymName, PtrVT));
1195
11
    return DAG.getNode(WebAssemblyISD::THROW, DL,
1196
11
                       MVT::Other, // outchain type
1197
11
                       {
1198
11
                           Op.getOperand(0), // inchain
1199
11
                           SymNode,          // exception symbol
1200
11
                           Op.getOperand(3)  // thrown value
1201
11
                       });
1202
11
  }
1203
226
  }
1204
226
}
1205
1206
SDValue
1207
WebAssemblyTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
1208
612
                                                  SelectionDAG &DAG) const {
1209
612
  SDLoc DL(Op);
1210
612
  // If sign extension operations are disabled, allow sext_inreg only if operand
1211
612
  // is a vector extract. SIMD does not depend on sign extension operations, but
1212
612
  // allowing sext_inreg in this context lets us have simple patterns to select
1213
612
  // extract_lane_s instructions. Expanding sext_inreg everywhere would be
1214
612
  // simpler in this file, but would necessitate large and brittle patterns to
1215
612
  // undo the expansion and select extract_lane_s instructions.
1216
612
  assert(!Subtarget->hasSignExt() && Subtarget->hasSIMD128());
1217
612
  if (Op.getOperand(0).getOpcode() == ISD::EXTRACT_VECTOR_ELT) {
1218
588
    const SDValue &Extract = Op.getOperand(0);
1219
588
    MVT VecT = Extract.getOperand(0).getSimpleValueType();
1220
588
    MVT ExtractedLaneT = static_cast<VTSDNode *>(Op.getOperand(1).getNode())
1221
588
                             ->getVT()
1222
588
                             .getSimpleVT();
1223
588
    MVT ExtractedVecT =
1224
588
        MVT::getVectorVT(ExtractedLaneT, 128 / ExtractedLaneT.getSizeInBits());
1225
588
    if (ExtractedVecT == VecT)
1226
584
      return Op;
1227
4
    // Bitcast vector to appropriate type to ensure ISel pattern coverage
1228
4
    const SDValue &Index = Extract.getOperand(1);
1229
4
    unsigned IndexVal =
1230
4
        static_cast<ConstantSDNode *>(Index.getNode())->getZExtValue();
1231
4
    unsigned Scale =
1232
4
        ExtractedVecT.getVectorNumElements() / VecT.getVectorNumElements();
1233
4
    assert(Scale > 1);
1234
4
    SDValue NewIndex =
1235
4
        DAG.getConstant(IndexVal * Scale, DL, Index.getValueType());
1236
4
    SDValue NewExtract = DAG.getNode(
1237
4
        ISD::EXTRACT_VECTOR_ELT, DL, Extract.getValueType(),
1238
4
        DAG.getBitcast(ExtractedVecT, Extract.getOperand(0)), NewIndex);
1239
4
    return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, Op.getValueType(),
1240
4
                       NewExtract, Op.getOperand(1));
1241
4
  }
1242
24
  // Otherwise expand
1243
24
  return SDValue();
1244
24
}
1245
1246
SDValue WebAssemblyTargetLowering::LowerBUILD_VECTOR(SDValue Op,
1247
1.50k
                                                     SelectionDAG &DAG) const {
1248
1.50k
  SDLoc DL(Op);
1249
1.50k
  const EVT VecT = Op.getValueType();
1250
1.50k
  const EVT LaneT = Op.getOperand(0).getValueType();
1251
1.50k
  const size_t Lanes = Op.getNumOperands();
1252
11.6k
  auto IsConstant = [](const SDValue &V) {
1253
11.6k
    return V.getOpcode() == ISD::Constant || 
V.getOpcode() == ISD::ConstantFP7.09k
;
1254
11.6k
  };
1255
1.50k
1256
1.50k
  // Find the most common operand, which is approximately the best to splat
1257
1.50k
  using Entry = std::pair<SDValue, size_t>;
1258
1.50k
  SmallVector<Entry, 16> ValueCounts;
1259
1.50k
  size_t NumConst = 0, NumDynamic = 0;
1260
10.3k
  for (const SDValue &Lane : Op->op_values()) {
1261
10.3k
    if (Lane.isUndef()) {
1262
7
      continue;
1263
10.3k
    } else if (IsConstant(Lane)) {
1264
4.48k
      NumConst++;
1265
5.83k
    } else {
1266
5.83k
      NumDynamic++;
1267
5.83k
    }
1268
10.3k
    auto CountIt = std::find_if(ValueCounts.begin(), ValueCounts.end(),
1269
14.9k
                                [&Lane](Entry A) { return A.first == Lane; });
1270
10.3k
    if (CountIt == ValueCounts.end()) {
1271
2.82k
      ValueCounts.emplace_back(Lane, 1);
1272
7.49k
    } else {
1273
7.49k
      CountIt->second++;
1274
7.49k
    }
1275
10.3k
  }
1276
1.50k
  auto CommonIt =
1277
1.50k
      std::max_element(ValueCounts.begin(), ValueCounts.end(),
1278
1.50k
                       [](Entry A, Entry B) 
{ return A.second < B.second; }1.32k
);
1279
1.50k
  assert(CommonIt != ValueCounts.end() && "Unexpected all-undef build_vector");
1280
1.50k
  SDValue SplatValue = CommonIt->first;
1281
1.50k
  size_t NumCommon = CommonIt->second;
1282
1.50k
1283
1.50k
  // If v128.const is available, consider using it instead of a splat
1284
1.50k
  if (Subtarget->hasUnimplementedSIMD128()) {
1285
1.12k
    // {i32,i64,f32,f64}.const opcode, and value
1286
1.12k
    const size_t ConstBytes = 1 + std::max(size_t(4), 16 / Lanes);
1287
1.12k
    // SIMD prefix and opcode
1288
1.12k
    const size_t SplatBytes = 2;
1289
1.12k
    const size_t SplatConstBytes = SplatBytes + ConstBytes;
1290
1.12k
    // SIMD prefix, opcode, and lane index
1291
1.12k
    const size_t ReplaceBytes = 3;
1292
1.12k
    const size_t ReplaceConstBytes = ReplaceBytes + ConstBytes;
1293
1.12k
    // SIMD prefix, v128.const opcode, and 128-bit value
1294
1.12k
    const size_t VecConstBytes = 18;
1295
1.12k
    // Initial v128.const and a replace_lane for each non-const operand
1296
1.12k
    const size_t ConstInitBytes = VecConstBytes + NumDynamic * ReplaceBytes;
1297
1.12k
    // Initial splat and all necessary replace_lanes
1298
1.12k
    const size_t SplatInitBytes =
1299
1.12k
        IsConstant(SplatValue)
1300
1.12k
            // Initial constant splat
1301
1.12k
            ? (SplatConstBytes +
1302
488
               // Constant replace_lanes
1303
488
               (NumConst - NumCommon) * ReplaceConstBytes +
1304
488
               // Dynamic replace_lanes
1305
488
               (NumDynamic * ReplaceBytes))
1306
1.12k
            // Initial dynamic splat
1307
1.12k
            : (SplatBytes +
1308
636
               // Constant replace_lanes
1309
636
               (NumConst * ReplaceConstBytes) +
1310
636
               // Dynamic replace_lanes
1311
636
               (NumDynamic - NumCommon) * ReplaceBytes);
1312
1.12k
    if (ConstInitBytes < SplatInitBytes) {
1313
18
      // Create build_vector that will lower to initial v128.const
1314
18
      SmallVector<SDValue, 16> ConstLanes;
1315
108
      for (const SDValue &Lane : Op->op_values()) {
1316
108
        if (IsConstant(Lane)) {
1317
106
          ConstLanes.push_back(Lane);
1318
106
        } else 
if (2
LaneT.isFloatingPoint()2
) {
1319
1
          ConstLanes.push_back(DAG.getConstantFP(0, DL, LaneT));
1320
1
        } else {
1321
1
          ConstLanes.push_back(DAG.getConstant(0, DL, LaneT));
1322
1
        }
1323
108
      }
1324
18
      SDValue Result = DAG.getBuildVector(VecT, DL, ConstLanes);
1325
18
      // Add replace_lane instructions for non-const lanes
1326
126
      for (size_t I = 0; I < Lanes; 
++I108
) {
1327
108
        const SDValue &Lane = Op->getOperand(I);
1328
108
        if (!Lane.isUndef() && !IsConstant(Lane))
1329
2
          Result = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VecT, Result, Lane,
1330
2
                               DAG.getConstant(I, DL, MVT::i32));
1331
108
      }
1332
18
      return Result;
1333
18
    }
1334
1.48k
  }
1335
1.48k
  // Use a splat for the initial vector
1336
1.48k
  SDValue Result = DAG.getSplatBuildVector(VecT, DL, SplatValue);
1337
1.48k
  // Add replace_lane instructions for other values
1338
11.7k
  for (size_t I = 0; I < Lanes; 
++I10.2k
) {
1339
10.2k
    const SDValue &Lane = Op->getOperand(I);
1340
10.2k
    if (Lane != SplatValue)
1341
1.24k
      Result = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VecT, Result, Lane,
1342
1.24k
                           DAG.getConstant(I, DL, MVT::i32));
1343
10.2k
  }
1344
1.48k
  return Result;
1345
1.48k
}
1346
1347
SDValue
1348
WebAssemblyTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
1349
21
                                               SelectionDAG &DAG) const {
1350
21
  SDLoc DL(Op);
1351
21
  ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(Op.getNode())->getMask();
1352
21
  MVT VecType = Op.getOperand(0).getSimpleValueType();
1353
21
  assert(VecType.is128BitVector() && "Unexpected shuffle vector type");
1354
21
  size_t LaneBytes = VecType.getVectorElementType().getSizeInBits() / 8;
1355
21
1356
21
  // Space for two vector args and sixteen mask indices
1357
21
  SDValue Ops[18];
1358
21
  size_t OpIdx = 0;
1359
21
  Ops[OpIdx++] = Op.getOperand(0);
1360
21
  Ops[OpIdx++] = Op.getOperand(1);
1361
21
1362
21
  // Expand mask indices to byte indices and materialize them as operands
1363
140
  for (int M : Mask) {
1364
476
    for (size_t J = 0; J < LaneBytes; 
++J336
) {
1365
336
      // Lower undefs (represented by -1 in mask) to zero
1366
336
      uint64_t ByteIndex = M == -1 ? 
0134
:
(uint64_t)M * LaneBytes + J202
;
1367
336
      Ops[OpIdx++] = DAG.getConstant(ByteIndex, DL, MVT::i32);
1368
336
    }
1369
140
  }
1370
21
1371
21
  return DAG.getNode(WebAssemblyISD::SHUFFLE, DL, Op.getValueType(), Ops);
1372
21
}
1373
1374
SDValue
1375
WebAssemblyTargetLowering::LowerAccessVectorElement(SDValue Op,
1376
6.96k
                                                    SelectionDAG &DAG) const {
1377
6.96k
  // Allow constant lane indices, expand variable lane indices
1378
6.96k
  SDNode *IdxNode = Op.getOperand(Op.getNumOperands() - 1).getNode();
1379
6.96k
  if (isa<ConstantSDNode>(IdxNode) || 
IdxNode->isUndef()60
)
1380
6.93k
    return Op;
1381
28
  else
1382
28
    // Perform default expansion
1383
28
    return SDValue();
1384
6.96k
}
1385
1386
112
static SDValue unrollVectorShift(SDValue Op, SelectionDAG &DAG) {
1387
112
  EVT LaneT = Op.getSimpleValueType().getVectorElementType();
1388
112
  // 32-bit and 64-bit unrolled shifts will have proper semantics
1389
112
  if (LaneT.bitsGE(MVT::i32))
1390
48
    return DAG.UnrollVectorOp(Op.getNode());
1391
64
  // Otherwise mask the shift value to get proper semantics from 32-bit shift
1392
64
  SDLoc DL(Op);
1393
64
  SDValue ShiftVal = Op.getOperand(1);
1394
64
  uint64_t MaskVal = LaneT.getSizeInBits() - 1;
1395
64
  SDValue MaskedShiftVal = DAG.getNode(
1396
64
      ISD::AND,                    // mask opcode
1397
64
      DL, ShiftVal.getValueType(), // masked value type
1398
64
      ShiftVal,                    // original shift value operand
1399
64
      DAG.getConstant(MaskVal, DL, ShiftVal.getValueType()) // mask operand
1400
64
  );
1401
64
1402
64
  return DAG.UnrollVectorOp(
1403
64
      DAG.getNode(Op.getOpcode(),        // original shift opcode
1404
64
                  DL, Op.getValueType(), // original return type
1405
64
                  Op.getOperand(0),      // original vector operand,
1406
64
                  MaskedShiftVal         // new masked shift value operand
1407
64
                  )
1408
64
          .getNode());
1409
64
}
1410
1411
SDValue WebAssemblyTargetLowering::LowerShift(SDValue Op,
1412
457
                                              SelectionDAG &DAG) const {
1413
457
  SDLoc DL(Op);
1414
457
1415
457
  // Only manually lower vector shifts
1416
457
  assert(Op.getSimpleValueType().isVector());
1417
457
1418
457
  // Expand all vector shifts until V8 fixes its implementation
1419
457
  // TODO: remove this once V8 is fixed
1420
457
  if (!Subtarget->hasUnimplementedSIMD128())
1421
48
    return unrollVectorShift(Op, DAG);
1422
409
1423
409
  // Unroll non-splat vector shifts
1424
409
  BuildVectorSDNode *ShiftVec;
1425
409
  SDValue SplatVal;
1426
409
  if (!(ShiftVec = dyn_cast<BuildVectorSDNode>(Op.getOperand(1).getNode())) ||
1427
409
      
!(SplatVal = ShiftVec->getSplatValue())345
)
1428
64
    return unrollVectorShift(Op, DAG);
1429
345
1430
345
  // All splats except i64x2 const splats are handled by patterns
1431
345
  auto *SplatConst = dyn_cast<ConstantSDNode>(SplatVal);
1432
345
  if (!SplatConst || 
Op.getSimpleValueType() != MVT::v2i64129
)
1433
327
    return Op;
1434
18
1435
18
  // i64x2 const splats are custom lowered to avoid unnecessary wraps
1436
18
  unsigned Opcode;
1437
18
  switch (Op.getOpcode()) {
1438
18
  case ISD::SHL:
1439
7
    Opcode = WebAssemblyISD::VEC_SHL;
1440
7
    break;
1441
18
  case ISD::SRA:
1442
7
    Opcode = WebAssemblyISD::VEC_SHR_S;
1443
7
    break;
1444
18
  case ISD::SRL:
1445
4
    Opcode = WebAssemblyISD::VEC_SHR_U;
1446
4
    break;
1447
18
  default:
1448
0
    llvm_unreachable("unexpected opcode");
1449
18
  }
1450
18
  APInt Shift = SplatConst->getAPIntValue().zextOrTrunc(32);
1451
18
  return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(0),
1452
18
                     DAG.getConstant(Shift, DL, MVT::i32));
1453
18
}
1454
1455
//===----------------------------------------------------------------------===//
1456
//                          WebAssembly Optimization Hooks
1457
//===----------------------------------------------------------------------===//