Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/Mips/MipsSERegisterInfo.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- MipsSERegisterInfo.cpp - MIPS32/64 Register 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 MIPS32/64 implementation of the TargetRegisterInfo
10
// class.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "MipsSERegisterInfo.h"
15
#include "Mips.h"
16
#include "MipsMachineFunction.h"
17
#include "MipsSEInstrInfo.h"
18
#include "MipsSubtarget.h"
19
#include "MipsTargetMachine.h"
20
#include "llvm/ADT/STLExtras.h"
21
#include "llvm/CodeGen/MachineFrameInfo.h"
22
#include "llvm/CodeGen/MachineFunction.h"
23
#include "llvm/CodeGen/MachineInstrBuilder.h"
24
#include "llvm/CodeGen/MachineRegisterInfo.h"
25
#include "llvm/CodeGen/TargetFrameLowering.h"
26
#include "llvm/CodeGen/TargetInstrInfo.h"
27
#include "llvm/IR/Constants.h"
28
#include "llvm/IR/DebugInfo.h"
29
#include "llvm/IR/Function.h"
30
#include "llvm/IR/Type.h"
31
#include "llvm/Support/Debug.h"
32
#include "llvm/Support/ErrorHandling.h"
33
#include "llvm/Support/raw_ostream.h"
34
#include "llvm/Target/TargetMachine.h"
35
#include "llvm/Target/TargetOptions.h"
36
37
using namespace llvm;
38
39
#define DEBUG_TYPE "mips-reg-info"
40
41
8.43k
MipsSERegisterInfo::MipsSERegisterInfo() : MipsRegisterInfo() {}
42
43
bool MipsSERegisterInfo::
44
37.6k
requiresRegisterScavenging(const MachineFunction &MF) const {
45
37.6k
  return true;
46
37.6k
}
47
48
bool MipsSERegisterInfo::
49
12.8k
requiresFrameIndexScavenging(const MachineFunction &MF) const {
50
12.8k
  return true;
51
12.8k
}
52
53
const TargetRegisterClass *
54
7
MipsSERegisterInfo::intRegClass(unsigned Size) const {
55
7
  if (Size == 4)
56
3
    return &Mips::GPR32RegClass;
57
4
58
4
  assert(Size == 8);
59
4
  return &Mips::GPR64RegClass;
60
4
}
61
62
/// Get the size of the offset supported by the given load/store/inline asm.
63
/// The result includes the effects of any scale factors applied to the
64
/// instruction immediate.
65
static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode,
66
13.8k
                                                    MachineOperand MO) {
67
13.8k
  switch (Opcode) {
68
13.8k
  case Mips::LD_B:
69
41
  case Mips::ST_B:
70
41
    return 10;
71
58
  case Mips::LD_H:
72
58
  case Mips::ST_H:
73
58
    return 10 + 1 /* scale factor */;
74
70
  case Mips::LD_W:
75
70
  case Mips::ST_W:
76
70
    return 10 + 2 /* scale factor */;
77
84
  case Mips::LD_D:
78
84
  case Mips::ST_D:
79
84
    return 10 + 3 /* scale factor */;
80
84
  case Mips::LL:
81
0
  case Mips::LL64:
82
0
  case Mips::LLD:
83
0
  case Mips::LLE:
84
0
  case Mips::SC:
85
0
  case Mips::SC64:
86
0
  case Mips::SCD:
87
0
  case Mips::SCE:
88
0
    return 16;
89
0
  case Mips::LLE_MM:
90
0
  case Mips::LL_MM:
91
0
  case Mips::SCE_MM:
92
0
  case Mips::SC_MM:
93
0
    return 12;
94
0
  case Mips::LL64_R6:
95
0
  case Mips::LL_R6:
96
0
  case Mips::LLD_R6:
97
0
  case Mips::SC64_R6:
98
0
  case Mips::SCD_R6:
99
0
  case Mips::SC_R6:
100
0
  case Mips::LL_MMR6:
101
0
  case Mips::SC_MMR6:
102
0
    return 9;
103
12
  case Mips::INLINEASM: {
104
12
    unsigned ConstraintID = InlineAsm::getMemoryConstraintID(MO.getImm());
105
12
    switch (ConstraintID) {
106
12
    case InlineAsm::Constraint_ZC: {
107
8
      const MipsSubtarget &Subtarget = MO.getParent()
108
8
                                           ->getParent()
109
8
                                           ->getParent()
110
8
                                           ->getSubtarget<MipsSubtarget>();
111
8
      if (Subtarget.inMicroMipsMode())
112
0
        return 12;
113
8
114
8
      if (Subtarget.hasMips32r6())
115
4
        return 9;
116
4
117
4
      return 16;
118
4
    }
119
4
    default:
120
4
      return 16;
121
0
    }
122
0
  }
123
13.5k
  default:
124
13.5k
    return 16;
125
13.8k
  }
126
13.8k
}
127
128
/// Get the scale factor applied to the immediate in the given load/store.
129
13.8k
static inline unsigned getLoadStoreOffsetAlign(const unsigned Opcode) {
130
13.8k
  switch (Opcode) {
131
13.8k
  case Mips::LD_H:
132
58
  case Mips::ST_H:
133
58
    return 2;
134
70
  case Mips::LD_W:
135
70
  case Mips::ST_W:
136
70
    return 4;
137
84
  case Mips::LD_D:
138
84
  case Mips::ST_D:
139
84
    return 8;
140
13.6k
  default:
141
13.6k
    return 1;
142
13.8k
  }
143
13.8k
}
144
145
void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
146
                                     unsigned OpNo, int FrameIndex,
147
                                     uint64_t StackSize,
148
13.8k
                                     int64_t SPOffset) const {
149
13.8k
  MachineInstr &MI = *II;
150
13.8k
  MachineFunction &MF = *MI.getParent()->getParent();
151
13.8k
  MachineFrameInfo &MFI = MF.getFrameInfo();
152
13.8k
  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
153
13.8k
154
13.8k
  MipsABIInfo ABI =
155
13.8k
      static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI();
156
13.8k
  const MipsRegisterInfo *RegInfo =
157
13.8k
    static_cast<const MipsRegisterInfo *>(MF.getSubtarget().getRegisterInfo());
158
13.8k
159
13.8k
  const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
160
13.8k
  int MinCSFI = 0;
161
13.8k
  int MaxCSFI = -1;
162
13.8k
163
13.8k
  if (CSI.size()) {
164
10.1k
    MinCSFI = CSI[0].getFrameIdx();
165
10.1k
    MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
166
10.1k
  }
167
13.8k
168
13.8k
  bool EhDataRegFI = MipsFI->isEhDataRegFI(FrameIndex);
169
13.8k
  bool IsISRRegFI = MipsFI->isISRRegFI(FrameIndex);
170
13.8k
  // The following stack frame objects are always referenced relative to $sp:
171
13.8k
  //  1. Outgoing arguments.
172
13.8k
  //  2. Pointer to dynamically allocated stack space.
173
13.8k
  //  3. Locations for callee-saved registers.
174
13.8k
  //  4. Locations for eh data registers.
175
13.8k
  //  5. Locations for ISR saved Coprocessor 0 registers 12 & 14.
176
13.8k
  // Everything else is referenced relative to whatever register
177
13.8k
  // getFrameRegister() returns.
178
13.8k
  unsigned FrameReg;
179
13.8k
180
13.8k
  if ((FrameIndex >= MinCSFI && 
FrameIndex <= MaxCSFI9.86k
) ||
EhDataRegFI6.27k
||
181
13.8k
      
IsISRRegFI6.16k
)
182
7.72k
    FrameReg = ABI.GetStackPtr();
183
6.12k
  else if (RegInfo->needsStackRealignment(MF)) {
184
765
    if (MFI.hasVarSizedObjects() && 
!MFI.isFixedObjectIndex(FrameIndex)91
)
185
75
      FrameReg = ABI.GetBasePtr();
186
690
    else if (MFI.isFixedObjectIndex(FrameIndex))
187
71
      FrameReg = getFrameRegister(MF);
188
619
    else
189
619
      FrameReg = ABI.GetStackPtr();
190
765
  } else
191
5.36k
    FrameReg = getFrameRegister(MF);
192
13.8k
193
13.8k
  // Calculate final offset.
194
13.8k
  // - There is no need to change the offset if the frame object is one of the
195
13.8k
  //   following: an outgoing argument, pointer to a dynamically allocated
196
13.8k
  //   stack space or a $gp restore location,
197
13.8k
  // - If the frame object is any of the following, its offset must be adjusted
198
13.8k
  //   by adding the size of the stack:
199
13.8k
  //   incoming argument, callee-saved register location or local variable.
200
13.8k
  bool IsKill = false;
201
13.8k
  int64_t Offset;
202
13.8k
203
13.8k
  Offset = SPOffset + (int64_t)StackSize;
204
13.8k
  Offset += MI.getOperand(OpNo + 1).getImm();
205
13.8k
206
13.8k
  LLVM_DEBUG(errs() << "Offset     : " << Offset << "\n"
207
13.8k
                    << "<--------->\n");
208
13.8k
209
13.8k
  if (!MI.isDebugValue()) {
210
13.8k
    // Make sure Offset fits within the field available.
211
13.8k
    // For MSA instructions, this is a 10-bit signed immediate (scaled by
212
13.8k
    // element size), otherwise it is a 16-bit signed immediate.
213
13.8k
    unsigned OffsetBitSize =
214
13.8k
        getLoadStoreOffsetSizeInBits(MI.getOpcode(), MI.getOperand(OpNo - 1));
215
13.8k
    unsigned OffsetAlign = getLoadStoreOffsetAlign(MI.getOpcode());
216
13.8k
217
13.8k
    if (OffsetBitSize < 16 && 
isInt<16>(Offset)257
&&
218
13.8k
        
(225
!isIntN(OffsetBitSize, Offset)225
||
219
225
         
OffsetToAlignment(Offset, OffsetAlign) != 0196
)) {
220
41
      // If we have an offset that needs to fit into a signed n-bit immediate
221
41
      // (where n < 16) and doesn't, but does fit into 16-bits then use an ADDiu
222
41
      MachineBasicBlock &MBB = *MI.getParent();
223
41
      DebugLoc DL = II->getDebugLoc();
224
41
      const TargetRegisterClass *PtrRC =
225
41
          ABI.ArePtrs64bit() ? 
&Mips::GPR64RegClass11
:
&Mips::GPR32RegClass30
;
226
41
      MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
227
41
      unsigned Reg = RegInfo.createVirtualRegister(PtrRC);
228
41
      const MipsSEInstrInfo &TII =
229
41
          *static_cast<const MipsSEInstrInfo *>(
230
41
              MBB.getParent()->getSubtarget().getInstrInfo());
231
41
      BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAddiuOp()), Reg)
232
41
          .addReg(FrameReg)
233
41
          .addImm(Offset);
234
41
235
41
      FrameReg = Reg;
236
41
      Offset = 0;
237
41
      IsKill = true;
238
13.8k
    } else if (!isInt<16>(Offset)) {
239
96
      // Otherwise split the offset into 16-bit pieces and add it in multiple
240
96
      // instructions.
241
96
      MachineBasicBlock &MBB = *MI.getParent();
242
96
      DebugLoc DL = II->getDebugLoc();
243
96
      unsigned NewImm = 0;
244
96
      const MipsSEInstrInfo &TII =
245
96
          *static_cast<const MipsSEInstrInfo *>(
246
96
              MBB.getParent()->getSubtarget().getInstrInfo());
247
96
      unsigned Reg = TII.loadImmediate(Offset, MBB, II, DL,
248
96
                                       OffsetBitSize == 16 ? 
&NewImm64
:
nullptr32
);
249
96
      BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAdduOp()), Reg).addReg(FrameReg)
250
96
        .addReg(Reg, RegState::Kill);
251
96
252
96
      FrameReg = Reg;
253
96
      Offset = SignExtend64<16>(NewImm);
254
96
      IsKill = true;
255
96
    }
256
13.8k
  }
257
13.8k
258
13.8k
  MI.getOperand(OpNo).ChangeToRegister(FrameReg, false, false, IsKill);
259
13.8k
  MI.getOperand(OpNo + 1).ChangeToImmediate(Offset);
260
13.8k
}