Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/XCore/XCoreInstrInfo.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- XCoreInstrInfo.cpp - XCore Instruction Information ----------------===//
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
// This file contains the XCore implementation of the TargetInstrInfo class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "XCoreInstrInfo.h"
14
#include "XCore.h"
15
#include "XCoreMachineFunctionInfo.h"
16
#include "llvm/ADT/STLExtras.h"
17
#include "llvm/CodeGen/MachineConstantPool.h"
18
#include "llvm/CodeGen/MachineFrameInfo.h"
19
#include "llvm/CodeGen/MachineInstrBuilder.h"
20
#include "llvm/CodeGen/MachineMemOperand.h"
21
#include "llvm/IR/Constants.h"
22
#include "llvm/IR/Function.h"
23
#include "llvm/MC/MCContext.h"
24
#include "llvm/Support/Debug.h"
25
#include "llvm/Support/ErrorHandling.h"
26
#include "llvm/Support/TargetRegistry.h"
27
28
using namespace llvm;
29
30
#define GET_INSTRINFO_CTOR_DTOR
31
#include "XCoreGenInstrInfo.inc"
32
33
namespace llvm {
34
namespace XCore {
35
36
  // XCore Condition Codes
37
  enum CondCode {
38
    COND_TRUE,
39
    COND_FALSE,
40
    COND_INVALID
41
  };
42
}
43
}
44
45
// Pin the vtable to this file.
46
0
void XCoreInstrInfo::anchor() {}
47
48
XCoreInstrInfo::XCoreInstrInfo()
49
  : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP),
50
81
    RI() {
51
81
}
52
53
5
static bool isZeroImm(const MachineOperand &op) {
54
5
  return op.isImm() && op.getImm() == 0;
55
5
}
56
57
/// isLoadFromStackSlot - If the specified machine instruction is a direct
58
/// load from a stack slot, return the virtual or physical register number of
59
/// the destination along with the FrameIndex of the loaded stack slot.  If
60
/// not, return 0.  This predicate must return 0 if the instruction has
61
/// any side effects other than loading from the stack slot.
62
unsigned XCoreInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
63
76
                                             int &FrameIndex) const {
64
76
  int Opcode = MI.getOpcode();
65
76
  if (Opcode == XCore::LDWFI)
66
4
  {
67
4
    if ((MI.getOperand(1).isFI()) &&  // is a stack slot
68
4
        (MI.getOperand(2).isImm()) && // the imm is zero
69
4
        (isZeroImm(MI.getOperand(2)))) {
70
3
      FrameIndex = MI.getOperand(1).getIndex();
71
3
      return MI.getOperand(0).getReg();
72
3
    }
73
73
  }
74
73
  return 0;
75
73
}
76
77
  /// isStoreToStackSlot - If the specified machine instruction is a direct
78
  /// store to a stack slot, return the virtual or physical register number of
79
  /// the source reg along with the FrameIndex of the loaded stack slot.  If
80
  /// not, return 0.  This predicate must return 0 if the instruction has
81
  /// any side effects other than storing to the stack slot.
82
unsigned XCoreInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
83
28
                                            int &FrameIndex) const {
84
28
  int Opcode = MI.getOpcode();
85
28
  if (Opcode == XCore::STWFI)
86
1
  {
87
1
    if ((MI.getOperand(1).isFI()) &&  // is a stack slot
88
1
        (MI.getOperand(2).isImm()) && // the imm is zero
89
1
        (isZeroImm(MI.getOperand(2)))) {
90
1
      FrameIndex = MI.getOperand(1).getIndex();
91
1
      return MI.getOperand(0).getReg();
92
1
    }
93
27
  }
94
27
  return 0;
95
27
}
96
97
//===----------------------------------------------------------------------===//
98
// Branch Analysis
99
//===----------------------------------------------------------------------===//
100
101
2.30k
static inline bool IsBRU(unsigned BrOpc) {
102
2.30k
  return BrOpc == XCore::BRFU_u6
103
2.30k
      || BrOpc == XCore::BRFU_lu6
104
2.30k
      || 
BrOpc == XCore::BRBU_u61.91k
105
2.30k
      || 
BrOpc == XCore::BRBU_lu61.91k
;
106
2.30k
}
107
108
1.99k
static inline bool IsBRT(unsigned BrOpc) {
109
1.99k
  return BrOpc == XCore::BRFT_ru6
110
1.99k
      || BrOpc == XCore::BRFT_lru6
111
1.99k
      || 
BrOpc == XCore::BRBT_ru61.87k
112
1.99k
      || 
BrOpc == XCore::BRBT_lru61.87k
;
113
1.99k
}
114
115
1.90k
static inline bool IsBRF(unsigned BrOpc) {
116
1.90k
  return BrOpc == XCore::BRFF_ru6
117
1.90k
      || BrOpc == XCore::BRFF_lru6
118
1.90k
      || 
BrOpc == XCore::BRBF_ru61.74k
119
1.90k
      || 
BrOpc == XCore::BRBF_lru61.74k
;
120
1.90k
}
121
122
100
static inline bool IsCondBranch(unsigned BrOpc) {
123
100
  return IsBRF(BrOpc) || 
IsBRT(BrOpc)79
;
124
100
}
125
126
0
static inline bool IsBR_JT(unsigned BrOpc) {
127
0
  return BrOpc == XCore::BR_JT
128
0
      || BrOpc == XCore::BR_JT32;
129
0
}
130
131
/// GetCondFromBranchOpc - Return the XCore CC that matches
132
/// the correspondent Branch instruction opcode.
133
static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc)
134
1.91k
{
135
1.91k
  if (IsBRT(BrOpc)) {
136
104
    return XCore::COND_TRUE;
137
1.80k
  } else if (IsBRF(BrOpc)) {
138
145
    return XCore::COND_FALSE;
139
1.66k
  } else {
140
1.66k
    return XCore::COND_INVALID;
141
1.66k
  }
142
1.91k
}
143
144
/// GetCondBranchFromCond - Return the Branch instruction
145
/// opcode that matches the cc.
146
static inline unsigned GetCondBranchFromCond(XCore::CondCode CC)
147
35
{
148
35
  switch (CC) {
149
35
  
default: 0
llvm_unreachable0
("Illegal condition code!");
150
35
  
case XCore::COND_TRUE : return XCore::BRFT_lru618
;
151
35
  
case XCore::COND_FALSE : return XCore::BRFF_lru617
;
152
35
  }
153
35
}
154
155
/// GetOppositeBranchCondition - Return the inverse of the specified
156
/// condition, e.g. turning COND_E to COND_NE.
157
static inline XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC)
158
24
{
159
24
  switch (CC) {
160
24
  
default: 0
llvm_unreachable0
("Illegal condition code!");
161
24
  
case XCore::COND_TRUE : return XCore::COND_FALSE10
;
162
24
  
case XCore::COND_FALSE : return XCore::COND_TRUE14
;
163
24
  }
164
24
}
165
166
/// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
167
/// true if it cannot be understood (e.g. it's a switch dispatch or isn't
168
/// implemented for a target).  Upon success, this returns false and returns
169
/// with the following information in various cases:
170
///
171
/// 1. If this block ends with no branches (it just falls through to its succ)
172
///    just return false, leaving TBB/FBB null.
173
/// 2. If this block ends with only an unconditional branch, it sets TBB to be
174
///    the destination block.
175
/// 3. If this block ends with an conditional branch and it falls through to
176
///    an successor block, it sets TBB to be the branch destination block and a
177
///    list of operands that evaluate the condition. These
178
///    operands can be passed to other TargetInstrInfo methods to create new
179
///    branches.
180
/// 4. If this block ends with an conditional branch and an unconditional
181
///    block, it returns the 'true' destination in TBB, the 'false' destination
182
///    in FBB, and a list of operands that evaluate the condition. These
183
///    operands can be passed to other TargetInstrInfo methods to create new
184
///    branches.
185
///
186
/// Note that removeBranch and insertBranch must be implemented to support
187
/// cases where this method returns success.
188
///
189
bool XCoreInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
190
                                   MachineBasicBlock *&TBB,
191
                                   MachineBasicBlock *&FBB,
192
                                   SmallVectorImpl<MachineOperand> &Cond,
193
2.52k
                                   bool AllowModify) const {
194
2.52k
  // If the block has no terminators, it just falls into the block after it.
195
2.52k
  MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
196
2.52k
  if (I == MBB.end())
197
87
    return false;
198
2.43k
199
2.43k
  if (!isUnpredicatedTerminator(*I))
200
263
    return false;
201
2.17k
202
2.17k
  // Get the last instruction in the block.
203
2.17k
  MachineInstr *LastInst = &*I;
204
2.17k
205
2.17k
  // If there is only one terminator instruction, process it.
206
2.17k
  if (I == MBB.begin() || 
!isUnpredicatedTerminator(*--I)1.93k
) {
207
2.12k
    if (IsBRU(LastInst->getOpcode())) {
208
248
      TBB = LastInst->getOperand(0).getMBB();
209
248
      return false;
210
248
    }
211
1.87k
212
1.87k
    XCore::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode());
213
1.87k
    if (BranchCode == XCore::COND_INVALID)
214
1.66k
      return true;  // Can't handle indirect branch.
215
211
216
211
    // Conditional branch
217
211
    // Block ends with fall-through condbranch.
218
211
219
211
    TBB = LastInst->getOperand(1).getMBB();
220
211
    Cond.push_back(MachineOperand::CreateImm(BranchCode));
221
211
    Cond.push_back(LastInst->getOperand(0));
222
211
    return false;
223
211
  }
224
51
225
51
  // Get the instruction before it if it's a terminator.
226
51
  MachineInstr *SecondLastInst = &*I;
227
51
228
51
  // If there are three terminators, we don't know what sort of block this is.
229
51
  if (SecondLastInst && I != MBB.begin() && 
isUnpredicatedTerminator(*--I)36
)
230
13
    return true;
231
38
232
38
  unsigned SecondLastOpc    = SecondLastInst->getOpcode();
233
38
  XCore::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc);
234
38
235
38
  // If the block ends with conditional branch followed by unconditional,
236
38
  // handle it.
237
38
  if (BranchCode != XCore::COND_INVALID
238
38
    && IsBRU(LastInst->getOpcode())) {
239
38
240
38
    TBB = SecondLastInst->getOperand(1).getMBB();
241
38
    Cond.push_back(MachineOperand::CreateImm(BranchCode));
242
38
    Cond.push_back(SecondLastInst->getOperand(0));
243
38
244
38
    FBB = LastInst->getOperand(0).getMBB();
245
38
    return false;
246
38
  }
247
0
248
0
  // If the block ends with two unconditional branches, handle it.  The second
249
0
  // one is not executed, so remove it.
250
0
  if (IsBRU(SecondLastInst->getOpcode()) &&
251
0
      IsBRU(LastInst->getOpcode())) {
252
0
    TBB = SecondLastInst->getOperand(0).getMBB();
253
0
    I = LastInst;
254
0
    if (AllowModify)
255
0
      I->eraseFromParent();
256
0
    return false;
257
0
  }
258
0
259
0
  // Likewise if it ends with a branch table followed by an unconditional branch.
260
0
  if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) {
261
0
    I = LastInst;
262
0
    if (AllowModify)
263
0
      I->eraseFromParent();
264
0
    return true;
265
0
  }
266
0
267
0
  // Otherwise, can't handle this.
268
0
  return true;
269
0
}
270
271
unsigned XCoreInstrInfo::insertBranch(MachineBasicBlock &MBB,
272
                                      MachineBasicBlock *TBB,
273
                                      MachineBasicBlock *FBB,
274
                                      ArrayRef<MachineOperand> Cond,
275
                                      const DebugLoc &DL,
276
123
                                      int *BytesAdded) const {
277
123
  // Shouldn't be a fall through.
278
123
  assert(TBB && "insertBranch must not be told to insert a fallthrough");
279
123
  assert((Cond.size() == 2 || Cond.size() == 0) &&
280
123
         "Unexpected number of components!");
281
123
  assert(!BytesAdded && "code size not handled");
282
123
283
123
  if (!FBB) { // One way branch.
284
122
    if (Cond.empty()) {
285
88
      // Unconditional branch
286
88
      BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(TBB);
287
88
    } else {
288
34
      // Conditional branch.
289
34
      unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
290
34
      BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
291
34
                             .addMBB(TBB);
292
34
    }
293
122
    return 1;
294
122
  }
295
1
296
1
  // Two-way Conditional branch.
297
1
  assert(Cond.size() == 2 && "Unexpected number of components!");
298
1
  unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
299
1
  BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
300
1
                         .addMBB(TBB);
301
1
  BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(FBB);
302
1
  return 2;
303
1
}
304
305
unsigned
306
142
XCoreInstrInfo::removeBranch(MachineBasicBlock &MBB, int *BytesRemoved) const {
307
142
  assert(!BytesRemoved && "code size not handled");
308
142
309
142
  MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
310
142
  if (I == MBB.end())
311
0
    return 0;
312
142
313
142
  if (!IsBRU(I->getOpcode()) && 
!IsCondBranch(I->getOpcode())36
)
314
14
    return 0;
315
128
316
128
  // Remove the branch.
317
128
  I->eraseFromParent();
318
128
319
128
  I = MBB.end();
320
128
321
128
  if (I == MBB.begin()) 
return 164
;
322
64
  --I;
323
64
  if (!IsCondBranch(I->getOpcode()))
324
51
    return 1;
325
13
326
13
  // Remove the branch.
327
13
  I->eraseFromParent();
328
13
  return 2;
329
13
}
330
331
void XCoreInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
332
                                 MachineBasicBlock::iterator I,
333
                                 const DebugLoc &DL, unsigned DestReg,
334
96
                                 unsigned SrcReg, bool KillSrc) const {
335
96
  bool GRDest = XCore::GRRegsRegClass.contains(DestReg);
336
96
  bool GRSrc  = XCore::GRRegsRegClass.contains(SrcReg);
337
96
338
96
  if (GRDest && 
GRSrc93
) {
339
82
    BuildMI(MBB, I, DL, get(XCore::ADD_2rus), DestReg)
340
82
      .addReg(SrcReg, getKillRegState(KillSrc))
341
82
      .addImm(0);
342
82
    return;
343
82
  }
344
14
345
14
  if (GRDest && 
SrcReg == XCore::SP11
) {
346
11
    BuildMI(MBB, I, DL, get(XCore::LDAWSP_ru6), DestReg).addImm(0);
347
11
    return;
348
11
  }
349
3
350
3
  if (DestReg == XCore::SP && GRSrc) {
351
3
    BuildMI(MBB, I, DL, get(XCore::SETSP_1r))
352
3
      .addReg(SrcReg, getKillRegState(KillSrc));
353
3
    return;
354
3
  }
355
0
  llvm_unreachable("Impossible reg-to-reg copy");
356
0
}
357
358
void XCoreInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
359
                                         MachineBasicBlock::iterator I,
360
                                         unsigned SrcReg, bool isKill,
361
                                         int FrameIndex,
362
                                         const TargetRegisterClass *RC,
363
                                         const TargetRegisterInfo *TRI) const
364
83
{
365
83
  DebugLoc DL;
366
83
  if (I != MBB.end() && !I->isDebugInstr())
367
83
    DL = I->getDebugLoc();
368
83
  MachineFunction *MF = MBB.getParent();
369
83
  const MachineFrameInfo &MFI = MF->getFrameInfo();
370
83
  MachineMemOperand *MMO = MF->getMachineMemOperand(
371
83
      MachinePointerInfo::getFixedStack(*MF, FrameIndex),
372
83
      MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),
373
83
      MFI.getObjectAlignment(FrameIndex));
374
83
  BuildMI(MBB, I, DL, get(XCore::STWFI))
375
83
    .addReg(SrcReg, getKillRegState(isKill))
376
83
    .addFrameIndex(FrameIndex)
377
83
    .addImm(0)
378
83
    .addMemOperand(MMO);
379
83
}
380
381
void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
382
                                          MachineBasicBlock::iterator I,
383
                                          unsigned DestReg, int FrameIndex,
384
                                          const TargetRegisterClass *RC,
385
                                          const TargetRegisterInfo *TRI) const
386
96
{
387
96
  DebugLoc DL;
388
96
  if (I != MBB.end() && !I->isDebugInstr())
389
96
    DL = I->getDebugLoc();
390
96
  MachineFunction *MF = MBB.getParent();
391
96
  const MachineFrameInfo &MFI = MF->getFrameInfo();
392
96
  MachineMemOperand *MMO = MF->getMachineMemOperand(
393
96
      MachinePointerInfo::getFixedStack(*MF, FrameIndex),
394
96
      MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
395
96
      MFI.getObjectAlignment(FrameIndex));
396
96
  BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg)
397
96
    .addFrameIndex(FrameIndex)
398
96
    .addImm(0)
399
96
    .addMemOperand(MMO);
400
96
}
401
402
bool XCoreInstrInfo::
403
24
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
404
24
  assert((Cond.size() == 2) &&
405
24
          "Invalid XCore branch condition!");
406
24
  Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));
407
24
  return false;
408
24
}
409
410
27
static inline bool isImmU6(unsigned val) {
411
27
  return val < (1 << 6);
412
27
}
413
414
39
static inline bool isImmU16(unsigned val) {
415
39
  return val < (1 << 16);
416
39
}
417
418
40
static bool isImmMskBitp(unsigned val) {
419
40
  if (!isMask_32(val)) {
420
38
    return false;
421
38
  }
422
2
  int N = Log2_32(val) + 1;
423
2
  return (N >= 1 && N <= 8) || 
N == 161
||
N == 241
||
N == 321
;
424
2
}
425
426
MachineBasicBlock::iterator XCoreInstrInfo::loadImmediate(
427
                                              MachineBasicBlock &MBB,
428
                                              MachineBasicBlock::iterator MI,
429
40
                                              unsigned Reg, uint64_t Value) const {
430
40
  DebugLoc dl;
431
40
  if (MI != MBB.end() && !MI->isDebugInstr())
432
40
    dl = MI->getDebugLoc();
433
40
  if (isImmMskBitp(Value)) {
434
1
    int N = Log2_32(Value) + 1;
435
1
    return BuildMI(MBB, MI, dl, get(XCore::MKMSK_rus), Reg)
436
1
        .addImm(N)
437
1
        .getInstr();
438
1
  }
439
39
  if (isImmU16(Value)) {
440
27
    int Opcode = isImmU6(Value) ? 
XCore::LDC_ru611
:
XCore::LDC_lru616
;
441
27
    return BuildMI(MBB, MI, dl, get(Opcode), Reg).addImm(Value).getInstr();
442
27
  }
443
12
  MachineConstantPool *ConstantPool = MBB.getParent()->getConstantPool();
444
12
  const Constant *C = ConstantInt::get(
445
12
        Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), Value);
446
12
  unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
447
12
  return BuildMI(MBB, MI, dl, get(XCore::LDWCP_lru6), Reg)
448
12
      .addConstantPoolIndex(Idx)
449
12
      .getInstr();
450
12
}