Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- WebAssemblyFastISel.cpp - WebAssembly FastISel 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 defines the WebAssembly-specific support for the FastISel
11
/// class. Some of the target-specific code is generated by tablegen in the file
12
/// WebAssemblyGenFastISel.inc, which is #included here.
13
///
14
/// TODO: kill flags
15
///
16
//===----------------------------------------------------------------------===//
17
18
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
19
#include "WebAssembly.h"
20
#include "WebAssemblyMachineFunctionInfo.h"
21
#include "WebAssemblySubtarget.h"
22
#include "WebAssemblyTargetMachine.h"
23
#include "llvm/Analysis/BranchProbabilityInfo.h"
24
#include "llvm/CodeGen/FastISel.h"
25
#include "llvm/CodeGen/FunctionLoweringInfo.h"
26
#include "llvm/CodeGen/MachineConstantPool.h"
27
#include "llvm/CodeGen/MachineFrameInfo.h"
28
#include "llvm/CodeGen/MachineInstrBuilder.h"
29
#include "llvm/CodeGen/MachineRegisterInfo.h"
30
#include "llvm/IR/DataLayout.h"
31
#include "llvm/IR/DerivedTypes.h"
32
#include "llvm/IR/Function.h"
33
#include "llvm/IR/GetElementPtrTypeIterator.h"
34
#include "llvm/IR/GlobalAlias.h"
35
#include "llvm/IR/GlobalVariable.h"
36
#include "llvm/IR/Instructions.h"
37
#include "llvm/IR/IntrinsicInst.h"
38
#include "llvm/IR/Operator.h"
39
#include "llvm/IR/PatternMatch.h"
40
41
using namespace llvm;
42
using namespace PatternMatch;
43
44
#define DEBUG_TYPE "wasm-fastisel"
45
46
namespace {
47
48
class WebAssemblyFastISel final : public FastISel {
49
  // All possible address modes.
50
  class Address {
51
  public:
52
    using BaseKind = enum { RegBase, FrameIndexBase };
53
54
  private:
55
    BaseKind Kind = RegBase;
56
    union {
57
      unsigned Reg;
58
      int FI;
59
    } Base;
60
61
    int64_t Offset = 0;
62
63
    const GlobalValue *GV = nullptr;
64
65
  public:
66
    // Innocuous defaults for our address.
67
99
    Address() { Base.Reg = 0; }
68
39
    void setKind(BaseKind K) {
69
39
      assert(!isSet() && "Can't change kind with non-zero base");
70
39
      Kind = K;
71
39
    }
72
0
    BaseKind getKind() const { return Kind; }
73
264
    bool isRegBase() const { return Kind == RegBase; }
74
0
    bool isFIBase() const { return Kind == FrameIndexBase; }
75
53
    void setReg(unsigned Reg) {
76
53
      assert(isRegBase() && "Invalid base register access!");
77
53
      assert(Base.Reg == 0 && "Overwriting non-zero register");
78
53
      Base.Reg = Reg;
79
53
    }
80
145
    unsigned getReg() const {
81
145
      assert(isRegBase() && "Invalid base register access!");
82
145
      return Base.Reg;
83
145
    }
84
39
    void setFI(unsigned FI) {
85
39
      assert(isFIBase() && "Invalid base frame index access!");
86
39
      assert(Base.FI == 0 && "Overwriting non-zero frame index");
87
39
      Base.FI = FI;
88
39
    }
89
39
    unsigned getFI() const {
90
39
      assert(isFIBase() && "Invalid base frame index access!");
91
39
      return Base.FI;
92
39
    }
93
94
18
    void setOffset(int64_t NewOffset) {
95
18
      assert(NewOffset >= 0 && "Offsets must be non-negative");
96
18
      Offset = NewOffset;
97
18
    }
98
122
    int64_t getOffset() const { return Offset; }
99
9
    void setGlobalValue(const GlobalValue *G) { GV = G; }
100
101
    const GlobalValue *getGlobalValue() const { return GV; }
101
83
    bool isSet() const {
102
83
      if (isRegBase()) {
103
83
        return Base.Reg != 0;
104
83
      } else {
105
0
        return Base.FI != 0;
106
0
      }
107
83
    }
108
  };
109
110
  /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
111
  /// right decision when generating code for different targets.
112
  const WebAssemblySubtarget *Subtarget;
113
  LLVMContext *Context;
114
115
private:
116
  // Utility helper routines
117
2.68k
  MVT::SimpleValueType getSimpleType(Type *Ty) {
118
2.68k
    EVT VT = TLI.getValueType(DL, Ty, /*AllowUnknown=*/true);
119
2.68k
    return VT.isSimple() ? 
VT.getSimpleVT().SimpleTy2.68k
120
2.68k
                         : 
MVT::INVALID_SIMPLE_VALUE_TYPE4
;
121
2.68k
  }
122
1.25k
  MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
123
1.25k
    switch (VT) {
124
1.25k
    case MVT::i1:
125
48
    case MVT::i8:
126
48
    case MVT::i16:
127
48
      return MVT::i32;
128
439
    case MVT::i32:
129
439
    case MVT::i64:
130
439
    case MVT::f32:
131
439
    case MVT::f64:
132
439
    case MVT::exnref:
133
439
      return VT;
134
439
    case MVT::f16:
135
2
      return MVT::f32;
136
561
    case MVT::v16i8:
137
561
    case MVT::v8i16:
138
561
    case MVT::v4i32:
139
561
    case MVT::v4f32:
140
561
      if (Subtarget->hasSIMD128())
141
561
        return VT;
142
0
      break;
143
201
    case MVT::v2i64:
144
201
    case MVT::v2f64:
145
201
      if (Subtarget->hasUnimplementedSIMD128())
146
200
        return VT;
147
1
      break;
148
3
    default:
149
3
      break;
150
4
    }
151
4
    return MVT::INVALID_SIMPLE_VALUE_TYPE;
152
4
  }
153
  bool computeAddress(const Value *Obj, Address &Addr);
154
  void materializeLoadStoreOperands(Address &Addr);
155
  void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
156
                            MachineMemOperand *MMO);
157
  unsigned maskI1Value(unsigned Reg, const Value *V);
158
  unsigned getRegForI1Value(const Value *V, bool &Not);
159
  unsigned zeroExtendToI32(unsigned Reg, const Value *V,
160
                           MVT::SimpleValueType From);
161
  unsigned signExtendToI32(unsigned Reg, const Value *V,
162
                           MVT::SimpleValueType From);
163
  unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
164
                      MVT::SimpleValueType To);
165
  unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
166
                      MVT::SimpleValueType To);
167
  unsigned getRegForUnsignedValue(const Value *V);
168
  unsigned getRegForSignedValue(const Value *V);
169
  unsigned getRegForPromotedValue(const Value *V, bool IsSigned);
170
  unsigned notValue(unsigned Reg);
171
  unsigned copyValue(unsigned Reg);
172
173
  // Backend specific FastISel code.
174
  unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
175
  unsigned fastMaterializeConstant(const Constant *C) override;
176
  bool fastLowerArguments() override;
177
178
  // Selection routines.
179
  bool selectCall(const Instruction *I);
180
  bool selectSelect(const Instruction *I);
181
  bool selectTrunc(const Instruction *I);
182
  bool selectZExt(const Instruction *I);
183
  bool selectSExt(const Instruction *I);
184
  bool selectICmp(const Instruction *I);
185
  bool selectFCmp(const Instruction *I);
186
  bool selectBitCast(const Instruction *I);
187
  bool selectLoad(const Instruction *I);
188
  bool selectStore(const Instruction *I);
189
  bool selectBr(const Instruction *I);
190
  bool selectRet(const Instruction *I);
191
  bool selectUnreachable(const Instruction *I);
192
193
public:
194
  // Backend specific FastISel code.
195
  WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo,
196
                      const TargetLibraryInfo *LibInfo)
197
666
      : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
198
666
    Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>();
199
666
    Context = &FuncInfo.Fn->getContext();
200
666
  }
201
202
  bool fastSelectInstruction(const Instruction *I) override;
203
204
#include "WebAssemblyGenFastISel.inc"
205
};
206
207
} // end anonymous namespace
208
209
122
bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {
210
122
  const User *U = nullptr;
211
122
  unsigned Opcode = Instruction::UserOp1;
212
122
  if (const auto *I = dyn_cast<Instruction>(Obj)) {
213
71
    // Don't walk into other basic blocks unless the object is an alloca from
214
71
    // another block, otherwise it may not have a virtual register assigned.
215
71
    if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
216
71
        
FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB31
) {
217
71
      Opcode = I->getOpcode();
218
71
      U = I;
219
71
    }
220
71
  } else 
if (const auto *51
C51
= dyn_cast<ConstantExpr>(Obj)) {
221
8
    Opcode = C->getOpcode();
222
8
    U = C;
223
8
  }
224
122
225
122
  if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
226
118
    if (Ty->getAddressSpace() > 255)
227
0
      // Fast instruction selection doesn't support the special
228
0
      // address spaces.
229
0
      return false;
230
122
231
122
  if (const auto *GV = dyn_cast<GlobalValue>(Obj)) {
232
18
    if (TLI.isPositionIndependent())
233
5
      return false;
234
13
    if (Addr.getGlobalValue())
235
0
      return false;
236
13
    if (GV->isThreadLocal())
237
4
      return false;
238
9
    Addr.setGlobalValue(GV);
239
9
    return true;
240
9
  }
241
104
242
104
  switch (Opcode) {
243
104
  default:
244
25
    break;
245
104
  case Instruction::BitCast: {
246
1
    // Look through bitcasts.
247
1
    return computeAddress(U->getOperand(0), Addr);
248
104
  }
249
104
  case Instruction::IntToPtr: {
250
2
    // Look past no-op inttoptrs.
251
2
    if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
252
2
        TLI.getPointerTy(DL))
253
2
      return computeAddress(U->getOperand(0), Addr);
254
0
    break;
255
0
  }
256
2
  case Instruction::PtrToInt: {
257
2
    // Look past no-op ptrtoints.
258
2
    if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
259
2
      return computeAddress(U->getOperand(0), Addr);
260
0
    break;
261
0
  }
262
32
  case Instruction::GetElementPtr: {
263
32
    Address SavedAddr = Addr;
264
32
    uint64_t TmpOffset = Addr.getOffset();
265
32
    // Non-inbounds geps can wrap; wasm's offsets can't.
266
32
    if (!cast<GEPOperator>(U)->isInBounds())
267
15
      goto unsupported_gep;
268
17
    // Iterate through the GEP folding the constants into offsets where
269
17
    // we can.
270
17
    for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
271
45
         GTI != E; 
++GTI28
) {
272
28
      const Value *Op = GTI.getOperand();
273
28
      if (StructType *STy = GTI.getStructTypeOrNull()) {
274
9
        const StructLayout *SL = DL.getStructLayout(STy);
275
9
        unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
276
9
        TmpOffset += SL->getElementOffset(Idx);
277
19
      } else {
278
19
        uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
279
19
        for (;;) {
280
19
          if (const auto *CI = dyn_cast<ConstantInt>(Op)) {
281
16
            // Constant-offset addressing.
282
16
            TmpOffset += CI->getSExtValue() * S;
283
16
            break;
284
16
          }
285
3
          if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
286
3
            // An unscaled add of a register. Set it as the new base.
287
3
            unsigned Reg = getRegForValue(Op);
288
3
            if (Reg == 0)
289
0
              return false;
290
3
            Addr.setReg(Reg);
291
3
            break;
292
3
          }
293
0
          if (canFoldAddIntoGEP(U, Op)) {
294
0
            // A compatible add with a constant operand. Fold the constant.
295
0
            auto *CI = cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
296
0
            TmpOffset += CI->getSExtValue() * S;
297
0
            // Iterate on the other operand.
298
0
            Op = cast<AddOperator>(Op)->getOperand(0);
299
0
            continue;
300
0
          }
301
0
          // Unsupported
302
0
          goto unsupported_gep;
303
0
        }
304
19
      }
305
28
    }
306
17
    // Don't fold in negative offsets.
307
17
    if (int64_t(TmpOffset) >= 0) {
308
16
      // Try to grab the base operand now.
309
16
      Addr.setOffset(TmpOffset);
310
16
      if (computeAddress(U->getOperand(0), Addr))
311
14
        return true;
312
3
    }
313
3
    // We failed, restore everything and try the other options.
314
3
    Addr = SavedAddr;
315
18
  unsupported_gep:
316
18
    break;
317
3
  }
318
40
  case Instruction::Alloca: {
319
40
    const auto *AI = cast<AllocaInst>(Obj);
320
40
    DenseMap<const AllocaInst *, int>::iterator SI =
321
40
        FuncInfo.StaticAllocaMap.find(AI);
322
40
    if (SI != FuncInfo.StaticAllocaMap.end()) {
323
40
      if (Addr.isSet()) {
324
1
        return false;
325
1
      }
326
39
      Addr.setKind(Address::FrameIndexBase);
327
39
      Addr.setFI(SI->second);
328
39
      return true;
329
39
    }
330
0
    break;
331
0
  }
332
2
  case Instruction::Add: {
333
2
    // Adds of constants are common and easy enough.
334
2
    const Value *LHS = U->getOperand(0);
335
2
    const Value *RHS = U->getOperand(1);
336
2
337
2
    if (isa<ConstantInt>(LHS))
338
0
      std::swap(LHS, RHS);
339
2
340
2
    if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
341
2
      uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
342
2
      if (int64_t(TmpOffset) >= 0) {
343
2
        Addr.setOffset(TmpOffset);
344
2
        return computeAddress(LHS, Addr);
345
2
      }
346
0
    }
347
0
348
0
    Address Backup = Addr;
349
0
    if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
350
0
      return true;
351
0
    Addr = Backup;
352
0
353
0
    break;
354
0
  }
355
0
  case Instruction::Sub: {
356
0
    // Subs of constants are common and easy enough.
357
0
    const Value *LHS = U->getOperand(0);
358
0
    const Value *RHS = U->getOperand(1);
359
0
360
0
    if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
361
0
      int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
362
0
      if (TmpOffset >= 0) {
363
0
        Addr.setOffset(TmpOffset);
364
0
        return computeAddress(LHS, Addr);
365
0
      }
366
0
    }
367
0
    break;
368
0
  }
369
43
  }
370
43
  if (Addr.isSet()) {
371
1
    return false;
372
1
  }
373
42
  unsigned Reg = getRegForValue(Obj);
374
42
  if (Reg == 0)
375
0
    return false;
376
42
  Addr.setReg(Reg);
377
42
  return Addr.getReg() != 0;
378
42
}
379
380
90
void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
381
90
  if (Addr.isRegBase()) {
382
51
    unsigned Reg = Addr.getReg();
383
51
    if (Reg == 0) {
384
8
      Reg = createResultReg(Subtarget->hasAddr64() ? 
&WebAssembly::I64RegClass0
385
8
                                                   : &WebAssembly::I32RegClass);
386
8
      unsigned Opc = Subtarget->hasAddr64() ? 
WebAssembly::CONST_I640
387
8
                                            : WebAssembly::CONST_I32;
388
8
      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
389
8
          .addImm(0);
390
8
      Addr.setReg(Reg);
391
8
    }
392
51
  }
393
90
}
394
395
void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
396
                                               const MachineInstrBuilder &MIB,
397
88
                                               MachineMemOperand *MMO) {
398
88
  // Set the alignment operand (this is rewritten in SetP2AlignOperands).
399
88
  // TODO: Disable SetP2AlignOperands for FastISel and just do it here.
400
88
  MIB.addImm(0);
401
88
402
88
  if (const GlobalValue *GV = Addr.getGlobalValue())
403
9
    MIB.addGlobalAddress(GV, Addr.getOffset());
404
79
  else
405
79
    MIB.addImm(Addr.getOffset());
406
88
407
88
  if (Addr.isRegBase())
408
49
    MIB.addReg(Addr.getReg());
409
39
  else
410
39
    MIB.addFrameIndex(Addr.getFI());
411
88
412
88
  MIB.addMemOperand(MMO);
413
88
}
414
415
41
unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
416
41
  return zeroExtendToI32(Reg, V, MVT::i1);
417
41
}
418
419
83
unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
420
83
  if (const auto *ICmp = dyn_cast<ICmpInst>(V))
421
35
    if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
422
27
      if (ICmp->isEquality() && 
C->isZero()20
&&
C->getType()->isIntegerTy(32)20
) {
423
20
        Not = ICmp->isTrueWhenEqual();
424
20
        return getRegForValue(ICmp->getOperand(0));
425
20
      }
426
63
427
63
  Value *NotV;
428
63
  if (match(V, m_Not(m_Value(NotV))) && 
V->getType()->isIntegerTy(32)2
) {
429
0
    Not = true;
430
0
    return getRegForValue(NotV);
431
0
  }
432
63
433
63
  Not = false;
434
63
  unsigned Reg = getRegForValue(V);
435
63
  if (Reg == 0)
436
22
    return 0;
437
41
  return maskI1Value(Reg, V);
438
41
}
439
440
unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
441
93
                                              MVT::SimpleValueType From) {
442
93
  if (Reg == 0)
443
0
    return 0;
444
93
445
93
  switch (From) {
446
93
  case MVT::i1:
447
63
    // If the value is naturally an i1, we don't need to mask it. We only know
448
63
    // if a value is naturally an i1 if it is definitely lowered by FastISel,
449
63
    // not a DAG ISel fallback.
450
63
    if (V != nullptr && isa<Argument>(V) && 
cast<Argument>(V)->hasZExtAttr()10
)
451
4
      return copyValue(Reg);
452
59
    break;
453
59
  case MVT::i8:
454
6
  case MVT::i16:
455
6
    break;
456
24
  case MVT::i32:
457
24
    return copyValue(Reg);
458
6
  default:
459
0
    return 0;
460
65
  }
461
65
462
65
  unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
463
65
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
464
65
          TII.get(WebAssembly::CONST_I32), Imm)
465
65
      .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
466
65
467
65
  unsigned Result = createResultReg(&WebAssembly::I32RegClass);
468
65
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
469
65
          TII.get(WebAssembly::AND_I32), Result)
470
65
      .addReg(Reg)
471
65
      .addReg(Imm);
472
65
473
65
  return Result;
474
65
}
475
476
unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
477
22
                                              MVT::SimpleValueType From) {
478
22
  if (Reg == 0)
479
0
    return 0;
480
22
481
22
  switch (From) {
482
22
  case MVT::i1:
483
2
  case MVT::i8:
484
2
  case MVT::i16:
485
2
    break;
486
20
  case MVT::i32:
487
20
    return copyValue(Reg);
488
2
  default:
489
0
    return 0;
490
2
  }
491
2
492
2
  unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
493
2
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
494
2
          TII.get(WebAssembly::CONST_I32), Imm)
495
2
      .addImm(32 - MVT(From).getSizeInBits());
496
2
497
2
  unsigned Left = createResultReg(&WebAssembly::I32RegClass);
498
2
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
499
2
          TII.get(WebAssembly::SHL_I32), Left)
500
2
      .addReg(Reg)
501
2
      .addReg(Imm);
502
2
503
2
  unsigned Right = createResultReg(&WebAssembly::I32RegClass);
504
2
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
505
2
          TII.get(WebAssembly::SHR_S_I32), Right)
506
2
      .addReg(Left)
507
2
      .addReg(Imm);
508
2
509
2
  return Right;
510
2
}
511
512
unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
513
                                         MVT::SimpleValueType From,
514
65
                                         MVT::SimpleValueType To) {
515
65
  if (To == MVT::i64) {
516
12
    if (From == MVT::i64)
517
12
      return copyValue(Reg);
518
0
519
0
    Reg = zeroExtendToI32(Reg, V, From);
520
0
521
0
    unsigned Result = createResultReg(&WebAssembly::I64RegClass);
522
0
    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
523
0
            TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
524
0
        .addReg(Reg);
525
0
    return Result;
526
0
  }
527
53
528
53
  if (To == MVT::i32)
529
52
    return zeroExtendToI32(Reg, V, From);
530
1
531
1
  return 0;
532
1
}
533
534
unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
535
                                         MVT::SimpleValueType From,
536
31
                                         MVT::SimpleValueType To) {
537
31
  if (To == MVT::i64) {
538
8
    if (From == MVT::i64)
539
8
      return copyValue(Reg);
540
0
541
0
    Reg = signExtendToI32(Reg, V, From);
542
0
543
0
    unsigned Result = createResultReg(&WebAssembly::I64RegClass);
544
0
    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
545
0
            TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
546
0
        .addReg(Reg);
547
0
    return Result;
548
0
  }
549
23
550
23
  if (To == MVT::i32)
551
22
    return signExtendToI32(Reg, V, From);
552
1
553
1
  return 0;
554
1
}
555
556
41
unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
557
41
  MVT::SimpleValueType From = getSimpleType(V->getType());
558
41
  MVT::SimpleValueType To = getLegalType(From);
559
41
  unsigned VReg = getRegForValue(V);
560
41
  if (VReg == 0)
561
2
    return 0;
562
39
  return zeroExtend(VReg, V, From, To);
563
39
}
564
565
31
unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
566
31
  MVT::SimpleValueType From = getSimpleType(V->getType());
567
31
  MVT::SimpleValueType To = getLegalType(From);
568
31
  unsigned VReg = getRegForValue(V);
569
31
  if (VReg == 0)
570
2
    return 0;
571
29
  return signExtend(VReg, V, From, To);
572
29
}
573
574
unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
575
70
                                                     bool IsSigned) {
576
70
  return IsSigned ? 
getRegForSignedValue(V)30
:
getRegForUnsignedValue(V)40
;
577
70
}
578
579
0
unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
580
0
  assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
581
0
582
0
  unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
583
0
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
584
0
          TII.get(WebAssembly::EQZ_I32), NotReg)
585
0
      .addReg(Reg);
586
0
  return NotReg;
587
0
}
588
589
68
unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
590
68
  unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
591
68
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
592
68
          ResultReg)
593
68
      .addReg(Reg);
594
68
  return ResultReg;
595
68
}
596
597
1
unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
598
1
  DenseMap<const AllocaInst *, int>::iterator SI =
599
1
      FuncInfo.StaticAllocaMap.find(AI);
600
1
601
1
  if (SI != FuncInfo.StaticAllocaMap.end()) {
602
1
    unsigned ResultReg =
603
1
        createResultReg(Subtarget->hasAddr64() ? 
&WebAssembly::I64RegClass0
604
1
                                               : &WebAssembly::I32RegClass);
605
1
    unsigned Opc =
606
1
        Subtarget->hasAddr64() ? 
WebAssembly::COPY_I640
: WebAssembly::COPY_I32;
607
1
    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
608
1
        .addFrameIndex(SI->second);
609
1
    return ResultReg;
610
1
  }
611
0
612
0
  return 0;
613
0
}
614
615
181
unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
616
181
  if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
617
24
    if (TLI.isPositionIndependent())
618
7
      return 0;
619
17
    if (GV->isThreadLocal())
620
5
      return 0;
621
12
    unsigned ResultReg =
622
12
        createResultReg(Subtarget->hasAddr64() ? 
&WebAssembly::I64RegClass0
623
12
                                               : &WebAssembly::I32RegClass);
624
12
    unsigned Opc = Subtarget->hasAddr64() ? 
WebAssembly::CONST_I640
625
12
                                          : WebAssembly::CONST_I32;
626
12
    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
627
12
        .addGlobalAddress(GV);
628
12
    return ResultReg;
629
12
  }
630
157
631
157
  // Let target-independent code handle it.
632
157
  return 0;
633
157
}
634
635
519
bool WebAssemblyFastISel::fastLowerArguments() {
636
519
  if (!FuncInfo.CanLowerReturn)
637
0
    return false;
638
519
639
519
  const Function *F = FuncInfo.Fn;
640
519
  if (F->isVarArg())
641
0
    return false;
642
519
643
519
  unsigned I = 0;
644
725
  for (auto const &Arg : F->args()) {
645
725
    const AttributeList &Attrs = F->getAttributes();
646
725
    if (Attrs.hasParamAttribute(I, Attribute::ByVal) ||
647
725
        
Attrs.hasParamAttribute(I, Attribute::SwiftSelf)722
||
648
725
        
Attrs.hasParamAttribute(I, Attribute::SwiftError)722
||
649
725
        
Attrs.hasParamAttribute(I, Attribute::InAlloca)722
||
650
725
        
Attrs.hasParamAttribute(I, Attribute::Nest)722
)
651
3
      return false;
652
722
653
722
    Type *ArgTy = Arg.getType();
654
722
    if (ArgTy->isStructTy() || 
ArgTy->isArrayTy()719
)
655
3
      return false;
656
719
    if (!Subtarget->hasSIMD128() && 
ArgTy->isVectorTy()175
)
657
0
      return false;
658
719
659
719
    unsigned Opc;
660
719
    const TargetRegisterClass *RC;
661
719
    switch (getSimpleType(ArgTy)) {
662
719
    case MVT::i1:
663
190
    case MVT::i8:
664
190
    case MVT::i16:
665
190
    case MVT::i32:
666
190
      Opc = WebAssembly::ARGUMENT_i32;
667
190
      RC = &WebAssembly::I32RegClass;
668
190
      break;
669
190
    case MVT::i64:
670
36
      Opc = WebAssembly::ARGUMENT_i64;
671
36
      RC = &WebAssembly::I64RegClass;
672
36
      break;
673
190
    case MVT::f32:
674
11
      Opc = WebAssembly::ARGUMENT_f32;
675
11
      RC = &WebAssembly::F32RegClass;
676
11
      break;
677
190
    case MVT::f64:
678
11
      Opc = WebAssembly::ARGUMENT_f64;
679
11
      RC = &WebAssembly::F64RegClass;
680
11
      break;
681
190
    case MVT::v16i8:
682
94
      Opc = WebAssembly::ARGUMENT_v16i8;
683
94
      RC = &WebAssembly::V128RegClass;
684
94
      break;
685
190
    case MVT::v8i16:
686
94
      Opc = WebAssembly::ARGUMENT_v8i16;
687
94
      RC = &WebAssembly::V128RegClass;
688
94
      break;
689
190
    case MVT::v4i32:
690
86
      Opc = WebAssembly::ARGUMENT_v4i32;
691
86
      RC = &WebAssembly::V128RegClass;
692
86
      break;
693
190
    case MVT::v2i64:
694
76
      Opc = WebAssembly::ARGUMENT_v2i64;
695
76
      RC = &WebAssembly::V128RegClass;
696
76
      break;
697
190
    case MVT::v4f32:
698
74
      Opc = WebAssembly::ARGUMENT_v4f32;
699
74
      RC = &WebAssembly::V128RegClass;
700
74
      break;
701
190
    case MVT::v2f64:
702
43
      Opc = WebAssembly::ARGUMENT_v2f64;
703
43
      RC = &WebAssembly::V128RegClass;
704
43
      break;
705
190
    case MVT::exnref:
706
0
      Opc = WebAssembly::ARGUMENT_exnref;
707
0
      RC = &WebAssembly::EXNREFRegClass;
708
0
      break;
709
190
    default:
710
4
      return false;
711
715
    }
712
715
    unsigned ResultReg = createResultReg(RC);
713
715
    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
714
715
        .addImm(I);
715
715
    updateValueMap(&Arg, ResultReg);
716
715
717
715
    ++I;
718
715
  }
719
519
720
519
  MRI.addLiveIn(WebAssembly::ARGUMENTS);
721
509
722
509
  auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
723
715
  for (auto const &Arg : F->args()) {
724
715
    MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType()));
725
715
    if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
726
1
      MFI->clearParamsAndResults();
727
1
      return false;
728
1
    }
729
714
    MFI->addParam(ArgTy);
730
714
  }
731
509
732
509
  
if (508
!F->getReturnType()->isVoidTy()508
) {
733
435
    MVT::SimpleValueType RetTy =
734
435
        getLegalType(getSimpleType(F->getReturnType()));
735
435
    if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
736
1
      MFI->clearParamsAndResults();
737
1
      return false;
738
1
    }
739
434
    MFI->addResult(RetTy);
740
434
  }
741
508
742
508
  
return true507
;
743
508
}
744
745
189
bool WebAssemblyFastISel::selectCall(const Instruction *I) {
746
189
  const auto *Call = cast<CallInst>(I);
747
189
748
189
  // TODO: Support tail calls in FastISel
749
189
  if (Call->isMustTailCall() || 
Call->isInlineAsm()185
||
750
189
      
Call->getFunctionType()->isVarArg()185
)
751
8
    return false;
752
181
753
181
  Function *Func = Call->getCalledFunction();
754
181
  if (Func && 
Func->isIntrinsic()153
)
755
92
    return false;
756
89
757
89
  bool IsDirect = Func != nullptr;
758
89
  if (!IsDirect && 
isa<ConstantExpr>(Call->getCalledValue())28
)
759
2
    return false;
760
87
761
87
  FunctionType *FuncTy = Call->getFunctionType();
762
87
  unsigned Opc;
763
87
  bool IsVoid = FuncTy->getReturnType()->isVoidTy();
764
87
  unsigned ResultReg;
765
87
  if (IsVoid) {
766
39
    Opc = IsDirect ? 
WebAssembly::CALL_VOID33
:
WebAssembly::PCALL_INDIRECT_VOID6
;
767
48
  } else {
768
48
    if (!Subtarget->hasSIMD128() && 
Call->getType()->isVectorTy()22
)
769
0
      return false;
770
48
771
48
    MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
772
48
    switch (RetTy) {
773
48
    case MVT::i1:
774
31
    case MVT::i8:
775
31
    case MVT::i16:
776
31
    case MVT::i32:
777
31
      Opc = IsDirect ? 
WebAssembly::CALL_i3220
:
WebAssembly::PCALL_INDIRECT_i3211
;
778
31
      ResultReg = createResultReg(&WebAssembly::I32RegClass);
779
31
      break;
780
31
    case MVT::i64:
781
4
      Opc = IsDirect ? 
WebAssembly::CALL_i642
:
WebAssembly::PCALL_INDIRECT_i642
;
782
4
      ResultReg = createResultReg(&WebAssembly::I64RegClass);
783
4
      break;
784
31
    case MVT::f32:
785
4
      Opc = IsDirect ? 
WebAssembly::CALL_f322
:
WebAssembly::PCALL_INDIRECT_f322
;
786
4
      ResultReg = createResultReg(&WebAssembly::F32RegClass);
787
4
      break;
788
31
    case MVT::f64:
789
4
      Opc = IsDirect ? 
WebAssembly::CALL_f642
:
WebAssembly::PCALL_INDIRECT_f642
;
790
4
      ResultReg = createResultReg(&WebAssembly::F64RegClass);
791
4
      break;
792
31
    case MVT::v16i8:
793
4
      Opc = IsDirect ? 
WebAssembly::CALL_v16i82
794
4
                     : 
WebAssembly::PCALL_INDIRECT_v16i82
;
795
4
      ResultReg = createResultReg(&WebAssembly::V128RegClass);
796
4
      break;
797
31
    case MVT::v8i16:
798
0
      Opc = IsDirect ? WebAssembly::CALL_v8i16
799
0
                     : WebAssembly::PCALL_INDIRECT_v8i16;
800
0
      ResultReg = createResultReg(&WebAssembly::V128RegClass);
801
0
      break;
802
31
    case MVT::v4i32:
803
0
      Opc = IsDirect ? WebAssembly::CALL_v4i32
804
0
                     : WebAssembly::PCALL_INDIRECT_v4i32;
805
0
      ResultReg = createResultReg(&WebAssembly::V128RegClass);
806
0
      break;
807
31
    case MVT::v2i64:
808
0
      Opc = IsDirect ? WebAssembly::CALL_v2i64
809
0
                     : WebAssembly::PCALL_INDIRECT_v2i64;
810
0
      ResultReg = createResultReg(&WebAssembly::V128RegClass);
811
0
      break;
812
31
    case MVT::v4f32:
813
0
      Opc = IsDirect ? WebAssembly::CALL_v4f32
814
0
                     : WebAssembly::PCALL_INDIRECT_v4f32;
815
0
      ResultReg = createResultReg(&WebAssembly::V128RegClass);
816
0
      break;
817
31
    case MVT::v2f64:
818
0
      Opc = IsDirect ? WebAssembly::CALL_v2f64
819
0
                     : WebAssembly::PCALL_INDIRECT_v2f64;
820
0
      ResultReg = createResultReg(&WebAssembly::V128RegClass);
821
0
      break;
822
31
    case MVT::exnref:
823
0
      Opc = IsDirect ? WebAssembly::CALL_exnref
824
0
                     : WebAssembly::PCALL_INDIRECT_exnref;
825
0
      ResultReg = createResultReg(&WebAssembly::EXNREFRegClass);
826
0
      break;
827
31
    default:
828
1
      return false;
829
86
    }
830
86
  }
831
86
832
86
  SmallVector<unsigned, 8> Args;
833
127
  for (unsigned I = 0, E = Call->getNumArgOperands(); I < E; 
++I41
) {
834
51
    Value *V = Call->getArgOperand(I);
835
51
    MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
836
51
    if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
837
0
      return false;
838
51
839
51
    const AttributeList &Attrs = Call->getAttributes();
840
51
    if (Attrs.hasParamAttribute(I, Attribute::ByVal) ||
841
51
        
Attrs.hasParamAttribute(I, Attribute::SwiftSelf)45
||
842
51
        
Attrs.hasParamAttribute(I, Attribute::SwiftError)45
||
843
51
        
Attrs.hasParamAttribute(I, Attribute::InAlloca)45
||
844
51
        
Attrs.hasParamAttribute(I, Attribute::Nest)45
)
845
6
      return false;
846
45
847
45
    unsigned Reg;
848
45
849
45
    if (Attrs.hasParamAttribute(I, Attribute::SExt))
850
1
      Reg = getRegForSignedValue(V);
851
44
    else if (Attrs.hasParamAttribute(I, Attribute::ZExt))
852
0
      Reg = getRegForUnsignedValue(V);
853
44
    else
854
44
      Reg = getRegForValue(V);
855
45
856
45
    if (Reg == 0)
857
4
      return false;
858
41
859
41
    Args.push_back(Reg);
860
41
  }
861
86
862
86
  unsigned CalleeReg = 0;
863
76
  if (!IsDirect) {
864
23
    CalleeReg = getRegForValue(Call->getCalledValue());
865
23
    if (!CalleeReg)
866
1
      return false;
867
75
  }
868
75
869
75
  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
870
75
871
75
  if (!IsVoid)
872
43
    MIB.addReg(ResultReg, RegState::Define);
873
75
874
75
  if (IsDirect)
875
53
    MIB.addGlobalAddress(Func);
876
22
  else
877
22
    MIB.addReg(CalleeReg);
878
75
879
75
  for (unsigned ArgReg : Args)
880
41
    MIB.addReg(ArgReg);
881
75
882
75
  if (!IsVoid)
883
43
    updateValueMap(Call, ResultReg);
884
75
  return true;
885
75
}
886
887
39
bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
888
39
  const auto *Select = cast<SelectInst>(I);
889
39
890
39
  bool Not;
891
39
  unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
892
39
  if (CondReg == 0)
893
20
    return false;
894
19
895
19
  unsigned TrueReg = getRegForValue(Select->getTrueValue());
896
19
  if (TrueReg == 0)
897
0
    return false;
898
19
899
19
  unsigned FalseReg = getRegForValue(Select->getFalseValue());
900
19
  if (FalseReg == 0)
901
0
    return false;
902
19
903
19
  if (Not)
904
4
    std::swap(TrueReg, FalseReg);
905
19
906
19
  unsigned Opc;
907
19
  const TargetRegisterClass *RC;
908
19
  switch (getSimpleType(Select->getType())) {
909
19
  case MVT::i1:
910
7
  case MVT::i8:
911
7
  case MVT::i16:
912
7
  case MVT::i32:
913
7
    Opc = WebAssembly::SELECT_I32;
914
7
    RC = &WebAssembly::I32RegClass;
915
7
    break;
916
7
  case MVT::i64:
917
4
    Opc = WebAssembly::SELECT_I64;
918
4
    RC = &WebAssembly::I64RegClass;
919
4
    break;
920
7
  case MVT::f32:
921
4
    Opc = WebAssembly::SELECT_F32;
922
4
    RC = &WebAssembly::F32RegClass;
923
4
    break;
924
7
  case MVT::f64:
925
4
    Opc = WebAssembly::SELECT_F64;
926
4
    RC = &WebAssembly::F64RegClass;
927
4
    break;
928
7
  case MVT::exnref:
929
0
    Opc = WebAssembly::SELECT_EXNREF;
930
0
    RC = &WebAssembly::EXNREFRegClass;
931
0
    break;
932
7
  default:
933
0
    return false;
934
19
  }
935
19
936
19
  unsigned ResultReg = createResultReg(RC);
937
19
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
938
19
      .addReg(TrueReg)
939
19
      .addReg(FalseReg)
940
19
      .addReg(CondReg);
941
19
942
19
  updateValueMap(Select, ResultReg);
943
19
  return true;
944
19
}
945
946
1
bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
947
1
  const auto *Trunc = cast<TruncInst>(I);
948
1
949
1
  unsigned Reg = getRegForValue(Trunc->getOperand(0));
950
1
  if (Reg == 0)
951
0
    return false;
952
1
953
1
  if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
954
0
    unsigned Result = createResultReg(&WebAssembly::I32RegClass);
955
0
    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
956
0
            TII.get(WebAssembly::I32_WRAP_I64), Result)
957
0
        .addReg(Reg);
958
0
    Reg = Result;
959
0
  }
960
1
961
1
  updateValueMap(Trunc, Reg);
962
1
  return true;
963
1
}
964
965
28
bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
966
28
  const auto *ZExt = cast<ZExtInst>(I);
967
28
968
28
  const Value *Op = ZExt->getOperand(0);
969
28
  MVT::SimpleValueType From = getSimpleType(Op->getType());
970
28
  MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
971
28
  unsigned In = getRegForValue(Op);
972
28
  if (In == 0)
973
2
    return false;
974
26
  unsigned Reg = zeroExtend(In, Op, From, To);
975
26
  if (Reg == 0)
976
1
    return false;
977
25
978
25
  updateValueMap(ZExt, Reg);
979
25
  return true;
980
25
}
981
982
4
bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
983
4
  const auto *SExt = cast<SExtInst>(I);
984
4
985
4
  const Value *Op = SExt->getOperand(0);
986
4
  MVT::SimpleValueType From = getSimpleType(Op->getType());
987
4
  MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
988
4
  unsigned In = getRegForValue(Op);
989
4
  if (In == 0)
990
2
    return false;
991
2
  unsigned Reg = signExtend(In, Op, From, To);
992
2
  if (Reg == 0)
993
1
    return false;
994
1
995
1
  updateValueMap(SExt, Reg);
996
1
  return true;
997
1
}
998
999
37
bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
1000
37
  const auto *ICmp = cast<ICmpInst>(I);
1001
37
1002
37
  bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
1003
37
  unsigned Opc;
1004
37
  bool IsSigned = false;
1005
37
  switch (ICmp->getPredicate()) {
1006
37
  case ICmpInst::ICMP_EQ:
1007
9
    Opc = I32 ? 
WebAssembly::EQ_I328
:
WebAssembly::EQ_I641
;
1008
9
    break;
1009
37
  case ICmpInst::ICMP_NE:
1010
2
    Opc = I32 ? 
WebAssembly::NE_I321
:
WebAssembly::NE_I641
;
1011
2
    break;
1012
37
  case ICmpInst::ICMP_UGT:
1013
2
    Opc = I32 ? 
WebAssembly::GT_U_I321
:
WebAssembly::GT_U_I641
;
1014
2
    break;
1015
37
  case ICmpInst::ICMP_UGE:
1016
2
    Opc = I32 ? 
WebAssembly::GE_U_I321
:
WebAssembly::GE_U_I641
;
1017
2
    break;
1018
37
  case ICmpInst::ICMP_ULT:
1019
4
    Opc = I32 ? 
WebAssembly::LT_U_I323
:
WebAssembly::LT_U_I641
;
1020
4
    break;
1021
37
  case ICmpInst::ICMP_ULE:
1022
2
    Opc = I32 ? 
WebAssembly::LE_U_I321
:
WebAssembly::LE_U_I641
;
1023
2
    break;
1024
37
  case ICmpInst::ICMP_SGT:
1025
2
    Opc = I32 ? 
WebAssembly::GT_S_I321
:
WebAssembly::GT_S_I641
;
1026
2
    IsSigned = true;
1027
2
    break;
1028
37
  case ICmpInst::ICMP_SGE:
1029
2
    Opc = I32 ? 
WebAssembly::GE_S_I321
:
WebAssembly::GE_S_I641
;
1030
2
    IsSigned = true;
1031
2
    break;
1032
37
  case ICmpInst::ICMP_SLT:
1033
10
    Opc = I32 ? 
WebAssembly::LT_S_I329
:
WebAssembly::LT_S_I641
;
1034
10
    IsSigned = true;
1035
10
    break;
1036
37
  case ICmpInst::ICMP_SLE:
1037
2
    Opc = I32 ? 
WebAssembly::LE_S_I321
:
WebAssembly::LE_S_I641
;
1038
2
    IsSigned = true;
1039
2
    break;
1040
37
  default:
1041
0
    return false;
1042
37
  }
1043
37
1044
37
  unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
1045
37
  if (LHS == 0)
1046
4
    return false;
1047
33
1048
33
  unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
1049
33
  if (RHS == 0)
1050
0
    return false;
1051
33
1052
33
  unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1053
33
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1054
33
      .addReg(LHS)
1055
33
      .addReg(RHS);
1056
33
  updateValueMap(ICmp, ResultReg);
1057
33
  return true;
1058
33
}
1059
1060
0
bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
1061
0
  const auto *FCmp = cast<FCmpInst>(I);
1062
0
1063
0
  unsigned LHS = getRegForValue(FCmp->getOperand(0));
1064
0
  if (LHS == 0)
1065
0
    return false;
1066
0
1067
0
  unsigned RHS = getRegForValue(FCmp->getOperand(1));
1068
0
  if (RHS == 0)
1069
0
    return false;
1070
0
1071
0
  bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1072
0
  unsigned Opc;
1073
0
  bool Not = false;
1074
0
  switch (FCmp->getPredicate()) {
1075
0
  case FCmpInst::FCMP_OEQ:
1076
0
    Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1077
0
    break;
1078
0
  case FCmpInst::FCMP_UNE:
1079
0
    Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1080
0
    break;
1081
0
  case FCmpInst::FCMP_OGT:
1082
0
    Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1083
0
    break;
1084
0
  case FCmpInst::FCMP_OGE:
1085
0
    Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1086
0
    break;
1087
0
  case FCmpInst::FCMP_OLT:
1088
0
    Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1089
0
    break;
1090
0
  case FCmpInst::FCMP_OLE:
1091
0
    Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1092
0
    break;
1093
0
  case FCmpInst::FCMP_UGT:
1094
0
    Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1095
0
    Not = true;
1096
0
    break;
1097
0
  case FCmpInst::FCMP_UGE:
1098
0
    Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1099
0
    Not = true;
1100
0
    break;
1101
0
  case FCmpInst::FCMP_ULT:
1102
0
    Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1103
0
    Not = true;
1104
0
    break;
1105
0
  case FCmpInst::FCMP_ULE:
1106
0
    Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1107
0
    Not = true;
1108
0
    break;
1109
0
  default:
1110
0
    return false;
1111
0
  }
1112
0
1113
0
  unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1114
0
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1115
0
      .addReg(LHS)
1116
0
      .addReg(RHS);
1117
0
1118
0
  if (Not)
1119
0
    ResultReg = notValue(ResultReg);
1120
0
1121
0
  updateValueMap(FCmp, ResultReg);
1122
0
  return true;
1123
0
}
1124
1125
4
bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
1126
4
  // Target-independent code can handle this, except it doesn't set the dead
1127
4
  // flag on the ARGUMENTS clobber, so we have to do that manually in order
1128
4
  // to satisfy code that expects this of isBitcast() instructions.
1129
4
  EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
1130
4
  EVT RetVT = TLI.getValueType(DL, I->getType());
1131
4
  if (!VT.isSimple() || !RetVT.isSimple())
1132
0
    return false;
1133
4
1134
4
  unsigned In = getRegForValue(I->getOperand(0));
1135
4
  if (In == 0)
1136
0
    return false;
1137
4
1138
4
  if (VT == RetVT) {
1139
0
    // No-op bitcast.
1140
0
    updateValueMap(I, In);
1141
0
    return true;
1142
0
  }
1143
4
1144
4
  unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
1145
4
                                        In, I->getOperand(0)->hasOneUse());
1146
4
  if (!Reg)
1147
0
    return false;
1148
4
  MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
1149
4
  --Iter;
1150
4
  assert(Iter->isBitcast());
1151
4
  Iter->setPhysRegsDeadExcept(ArrayRef<unsigned>(), TRI);
1152
4
  updateValueMap(I, Reg);
1153
4
  return true;
1154
4
}
1155
1156
44
bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
1157
44
  const auto *Load = cast<LoadInst>(I);
1158
44
  if (Load->isAtomic())
1159
0
    return false;
1160
44
  if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
1161
0
    return false;
1162
44
1163
44
  Address Addr;
1164
44
  if (!computeAddress(Load->getPointerOperand(), Addr))
1165
5
    return false;
1166
39
1167
39
  // TODO: Fold a following sign-/zero-extend into the load instruction.
1168
39
1169
39
  unsigned Opc;
1170
39
  const TargetRegisterClass *RC;
1171
39
  switch (getSimpleType(Load->getType())) {
1172
39
  case MVT::i1:
1173
4
  case MVT::i8:
1174
4
    Opc = WebAssembly::LOAD8_U_I32;
1175
4
    RC = &WebAssembly::I32RegClass;
1176
4
    break;
1177
4
  case MVT::i16:
1178
0
    Opc = WebAssembly::LOAD16_U_I32;
1179
0
    RC = &WebAssembly::I32RegClass;
1180
0
    break;
1181
25
  case MVT::i32:
1182
25
    Opc = WebAssembly::LOAD_I32;
1183
25
    RC = &WebAssembly::I32RegClass;
1184
25
    break;
1185
4
  case MVT::i64:
1186
4
    Opc = WebAssembly::LOAD_I64;
1187
4
    RC = &WebAssembly::I64RegClass;
1188
4
    break;
1189
4
  case MVT::f32:
1190
1
    Opc = WebAssembly::LOAD_F32;
1191
1
    RC = &WebAssembly::F32RegClass;
1192
1
    break;
1193
5
  case MVT::f64:
1194
5
    Opc = WebAssembly::LOAD_F64;
1195
5
    RC = &WebAssembly::F64RegClass;
1196
5
    break;
1197
4
  default:
1198
0
    return false;
1199
39
  }
1200
39
1201
39
  materializeLoadStoreOperands(Addr);
1202
39
1203
39
  unsigned ResultReg = createResultReg(RC);
1204
39
  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
1205
39
                     ResultReg);
1206
39
1207
39
  addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1208
39
1209
39
  updateValueMap(Load, ResultReg);
1210
39
  return true;
1211
39
}
1212
1213
55
bool WebAssemblyFastISel::selectStore(const Instruction *I) {
1214
55
  const auto *Store = cast<StoreInst>(I);
1215
55
  if (Store->isAtomic())
1216
0
    return false;
1217
55
  if (!Subtarget->hasSIMD128() &&
1218
55
      Store->getValueOperand()->getType()->isVectorTy())
1219
0
    return false;
1220
55
1221
55
  Address Addr;
1222
55
  if (!computeAddress(Store->getPointerOperand(), Addr))
1223
4
    return false;
1224
51
1225
51
  unsigned Opc;
1226
51
  bool VTIsi1 = false;
1227
51
  switch (getSimpleType(Store->getValueOperand()->getType())) {
1228
51
  case MVT::i1:
1229
0
    VTIsi1 = true;
1230
0
    LLVM_FALLTHROUGH;
1231
6
  case MVT::i8:
1232
6
    Opc = WebAssembly::STORE8_I32;
1233
6
    break;
1234
0
  case MVT::i16:
1235
0
    Opc = WebAssembly::STORE16_I32;
1236
0
    break;
1237
37
  case MVT::i32:
1238
37
    Opc = WebAssembly::STORE_I32;
1239
37
    break;
1240
2
  case MVT::i64:
1241
2
    Opc = WebAssembly::STORE_I64;
1242
2
    break;
1243
1
  case MVT::f32:
1244
1
    Opc = WebAssembly::STORE_F32;
1245
1
    break;
1246
5
  case MVT::f64:
1247
5
    Opc = WebAssembly::STORE_F64;
1248
5
    break;
1249
0
  default:
1250
0
    return false;
1251
51
  }
1252
51
1253
51
  materializeLoadStoreOperands(Addr);
1254
51
1255
51
  unsigned ValueReg = getRegForValue(Store->getValueOperand());
1256
51
  if (ValueReg == 0)
1257
2
    return false;
1258
49
  if (VTIsi1)
1259
0
    ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
1260
49
1261
49
  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
1262
49
1263
49
  addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1264
49
1265
49
  MIB.addReg(ValueReg);
1266
49
  return true;
1267
49
}
1268
1269
101
bool WebAssemblyFastISel::selectBr(const Instruction *I) {
1270
101
  const auto *Br = cast<BranchInst>(I);
1271
101
  if (Br->isUnconditional()) {
1272
57
    MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
1273
57
    fastEmitBranch(MSucc, Br->getDebugLoc());
1274
57
    return true;
1275
57
  }
1276
44
1277
44
  MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
1278
44
  MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
1279
44
1280
44
  bool Not;
1281
44
  unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
1282
44
  if (CondReg == 0)
1283
2
    return false;
1284
42
1285
42
  unsigned Opc = WebAssembly::BR_IF;
1286
42
  if (Not)
1287
5
    Opc = WebAssembly::BR_UNLESS;
1288
42
1289
42
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1290
42
      .addMBB(TBB)
1291
42
      .addReg(CondReg);
1292
42
1293
42
  finishCondBranch(Br->getParent(), TBB, FBB);
1294
42
  return true;
1295
42
}
1296
1297
661
bool WebAssemblyFastISel::selectRet(const Instruction *I) {
1298
661
  if (!FuncInfo.CanLowerReturn)
1299
147
    return false;
1300
514
1301
514
  const auto *Ret = cast<ReturnInst>(I);
1302
514
1303
514
  if (Ret->getNumOperands() == 0) {
1304
75
    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1305
75
            TII.get(WebAssembly::RETURN_VOID));
1306
75
    return true;
1307
75
  }
1308
439
1309
439
  Value *RV = Ret->getOperand(0);
1310
439
  if (!Subtarget->hasSIMD128() && 
RV->getType()->isVectorTy()115
)
1311
0
    return false;
1312
439
1313
439
  unsigned Opc;
1314
439
  switch (getSimpleType(RV->getType())) {
1315
439
  case MVT::i1:
1316
101
  case MVT::i8:
1317
101
  case MVT::i16:
1318
101
  case MVT::i32:
1319
101
    Opc = WebAssembly::RETURN_I32;
1320
101
    break;
1321
101
  case MVT::i64:
1322
14
    Opc = WebAssembly::RETURN_I64;
1323
14
    break;
1324
101
  case MVT::f32:
1325
12
    Opc = WebAssembly::RETURN_F32;
1326
12
    break;
1327
101
  case MVT::f64:
1328
12
    Opc = WebAssembly::RETURN_F64;
1329
12
    break;
1330
101
  case MVT::v16i8:
1331
57
    Opc = WebAssembly::RETURN_v16i8;
1332
57
    break;
1333
101
  case MVT::v8i16:
1334
53
    Opc = WebAssembly::RETURN_v8i16;
1335
53
    break;
1336
101
  case MVT::v4i32:
1337
51
    Opc = WebAssembly::RETURN_v4i32;
1338
51
    break;
1339
101
  case MVT::v2i64:
1340
51
    Opc = WebAssembly::RETURN_v2i64;
1341
51
    break;
1342
101
  case MVT::v4f32:
1343
52
    Opc = WebAssembly::RETURN_v4f32;
1344
52
    break;
1345
101
  case MVT::v2f64:
1346
31
    Opc = WebAssembly::RETURN_v2f64;
1347
31
    break;
1348
101
  case MVT::exnref:
1349
0
    Opc = WebAssembly::RETURN_EXNREF;
1350
0
    break;
1351
101
  default:
1352
5
    return false;
1353
434
  }
1354
434
1355
434
  unsigned Reg;
1356
434
  if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
1357
0
    Reg = getRegForSignedValue(RV);
1358
434
  else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
1359
1
    Reg = getRegForUnsignedValue(RV);
1360
433
  else
1361
433
    Reg = getRegForValue(RV);
1362
434
1363
434
  if (Reg == 0)
1364
9
    return false;
1365
425
1366
425
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg);
1367
425
  return true;
1368
425
}
1369
1370
16
bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
1371
16
  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1372
16
          TII.get(WebAssembly::UNREACHABLE));
1373
16
  return true;
1374
16
}
1375
1376
1.49k
bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
1377
1.49k
  switch (I->getOpcode()) {
1378
1.49k
  case Instruction::Call:
1379
189
    if (selectCall(I))
1380
75
      return true;
1381
114
    break;
1382
114
  case Instruction::Select:
1383
39
    return selectSelect(I);
1384
114
  case Instruction::Trunc:
1385
1
    return selectTrunc(I);
1386
114
  case Instruction::ZExt:
1387
28
    return selectZExt(I);
1388
114
  case Instruction::SExt:
1389
4
    return selectSExt(I);
1390
114
  case Instruction::ICmp:
1391
37
    return selectICmp(I);
1392
114
  case Instruction::FCmp:
1393
0
    return selectFCmp(I);
1394
114
  case Instruction::BitCast:
1395
4
    return selectBitCast(I);
1396
114
  case Instruction::Load:
1397
44
    return selectLoad(I);
1398
114
  case Instruction::Store:
1399
55
    return selectStore(I);
1400
114
  case Instruction::Br:
1401
101
    return selectBr(I);
1402
661
  case Instruction::Ret:
1403
661
    return selectRet(I);
1404
114
  case Instruction::Unreachable:
1405
16
    return selectUnreachable(I);
1406
318
  default:
1407
318
    break;
1408
432
  }
1409
432
1410
432
  // Fall back to target-independent instruction selection.
1411
432
  return selectOperator(I, I->getOpcode());
1412
432
}
1413
1414
FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo,
1415
666
                                      const TargetLibraryInfo *LibInfo) {
1416
666
  return new WebAssemblyFastISel(FuncInfo, LibInfo);
1417
666
}