Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/BPF/BPFInstrInfo.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- BPFInstrInfo.cpp - BPF Instruction Information ----------*- C++ -*-===//
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 BPF implementation of the TargetInstrInfo class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "BPFInstrInfo.h"
14
#include "BPF.h"
15
#include "llvm/ADT/SmallVector.h"
16
#include "llvm/CodeGen/MachineBasicBlock.h"
17
#include "llvm/CodeGen/MachineInstrBuilder.h"
18
#include "llvm/IR/DebugLoc.h"
19
#include "llvm/Support/ErrorHandling.h"
20
#include <cassert>
21
#include <iterator>
22
23
#define GET_INSTRINFO_CTOR_DTOR
24
#include "BPFGenInstrInfo.inc"
25
26
using namespace llvm;
27
28
BPFInstrInfo::BPFInstrInfo()
29
212
    : BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {}
30
31
void BPFInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
32
                               MachineBasicBlock::iterator I,
33
                               const DebugLoc &DL, unsigned DestReg,
34
297
                               unsigned SrcReg, bool KillSrc) const {
35
297
  if (BPF::GPRRegClass.contains(DestReg, SrcReg))
36
263
    BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg)
37
263
        .addReg(SrcReg, getKillRegState(KillSrc));
38
34
  else if (BPF::GPR32RegClass.contains(DestReg, SrcReg))
39
34
    BuildMI(MBB, I, DL, get(BPF::MOV_rr_32), DestReg)
40
34
        .addReg(SrcReg, getKillRegState(KillSrc));
41
34
  else
42
34
    
llvm_unreachable0
("Impossible reg-to-reg copy");
43
297
}
44
45
8
void BPFInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const {
46
8
  unsigned DstReg = MI->getOperand(0).getReg();
47
8
  unsigned SrcReg = MI->getOperand(1).getReg();
48
8
  uint64_t CopyLen = MI->getOperand(2).getImm();
49
8
  uint64_t Alignment = MI->getOperand(3).getImm();
50
8
  unsigned ScratchReg = MI->getOperand(4).getReg();
51
8
  MachineBasicBlock *BB = MI->getParent();
52
8
  DebugLoc dl = MI->getDebugLoc();
53
8
  unsigned LdOpc, StOpc;
54
8
55
8
  switch (Alignment) {
56
8
  case 1:
57
2
    LdOpc = BPF::LDB;
58
2
    StOpc = BPF::STB;
59
2
    break;
60
8
  case 2:
61
2
    LdOpc = BPF::LDH;
62
2
    StOpc = BPF::STH;
63
2
    break;
64
8
  case 4:
65
2
    LdOpc = BPF::LDW;
66
2
    StOpc = BPF::STW;
67
2
    break;
68
8
  case 8:
69
2
    LdOpc = BPF::LDD;
70
2
    StOpc = BPF::STD;
71
2
    break;
72
8
  default:
73
0
    llvm_unreachable("unsupported memcpy alignment");
74
8
  }
75
8
76
8
  unsigned IterationNum = CopyLen >> Log2_64(Alignment);
77
48
  for(unsigned I = 0; I < IterationNum; 
++I40
) {
78
40
    BuildMI(*BB, MI, dl, get(LdOpc))
79
40
            .addReg(ScratchReg, RegState::Define).addReg(SrcReg)
80
40
            .addImm(I * Alignment);
81
40
    BuildMI(*BB, MI, dl, get(StOpc))
82
40
            .addReg(ScratchReg, RegState::Kill).addReg(DstReg)
83
40
            .addImm(I * Alignment);
84
40
  }
85
8
86
8
  unsigned BytesLeft = CopyLen & (Alignment - 1);
87
8
  unsigned Offset = IterationNum * Alignment;
88
8
  bool Hanging4Byte = BytesLeft & 0x4;
89
8
  bool Hanging2Byte = BytesLeft & 0x2;
90
8
  bool Hanging1Byte = BytesLeft & 0x1;
91
8
  if (Hanging4Byte) {
92
0
    BuildMI(*BB, MI, dl, get(BPF::LDW))
93
0
            .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
94
0
    BuildMI(*BB, MI, dl, get(BPF::STW))
95
0
            .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
96
0
    Offset += 4;
97
0
  }
98
8
  if (Hanging2Byte) {
99
4
    BuildMI(*BB, MI, dl, get(BPF::LDH))
100
4
            .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
101
4
    BuildMI(*BB, MI, dl, get(BPF::STH))
102
4
            .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
103
4
    Offset += 2;
104
4
  }
105
8
  if (Hanging1Byte) {
106
6
    BuildMI(*BB, MI, dl, get(BPF::LDB))
107
6
            .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
108
6
    BuildMI(*BB, MI, dl, get(BPF::STB))
109
6
            .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
110
6
  }
111
8
112
8
  BB->erase(MI);
113
8
}
114
115
422
bool BPFInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
116
422
  if (MI.getOpcode() == BPF::MEMCPY) {
117
8
    expandMEMCPY(MI);
118
8
    return true;
119
8
  }
120
414
121
414
  return false;
122
414
}
123
124
void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
125
                                       MachineBasicBlock::iterator I,
126
                                       unsigned SrcReg, bool IsKill, int FI,
127
                                       const TargetRegisterClass *RC,
128
17
                                       const TargetRegisterInfo *TRI) const {
129
17
  DebugLoc DL;
130
17
  if (I != MBB.end())
131
17
    DL = I->getDebugLoc();
132
17
133
17
  if (RC == &BPF::GPRRegClass)
134
17
    BuildMI(MBB, I, DL, get(BPF::STD))
135
17
        .addReg(SrcReg, getKillRegState(IsKill))
136
17
        .addFrameIndex(FI)
137
17
        .addImm(0);
138
0
  else if (RC == &BPF::GPR32RegClass)
139
0
    BuildMI(MBB, I, DL, get(BPF::STW32))
140
0
        .addReg(SrcReg, getKillRegState(IsKill))
141
0
        .addFrameIndex(FI)
142
0
        .addImm(0);
143
0
  else
144
0
    llvm_unreachable("Can't store this register to stack slot");
145
17
}
146
147
void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
148
                                        MachineBasicBlock::iterator I,
149
                                        unsigned DestReg, int FI,
150
                                        const TargetRegisterClass *RC,
151
20
                                        const TargetRegisterInfo *TRI) const {
152
20
  DebugLoc DL;
153
20
  if (I != MBB.end())
154
20
    DL = I->getDebugLoc();
155
20
156
20
  if (RC == &BPF::GPRRegClass)
157
20
    BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0);
158
0
  else if (RC == &BPF::GPR32RegClass)
159
0
    BuildMI(MBB, I, DL, get(BPF::LDW32), DestReg).addFrameIndex(FI).addImm(0);
160
0
  else
161
0
    llvm_unreachable("Can't load this register from stack slot");
162
20
}
163
164
bool BPFInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
165
                                 MachineBasicBlock *&TBB,
166
                                 MachineBasicBlock *&FBB,
167
                                 SmallVectorImpl<MachineOperand> &Cond,
168
5.76k
                                 bool AllowModify) const {
169
5.76k
  // Start from the bottom of the block and work up, examining the
170
5.76k
  // terminator instructions.
171
5.76k
  MachineBasicBlock::iterator I = MBB.end();
172
6.55k
  while (I != MBB.begin()) {
173
6.45k
    --I;
174
6.45k
    if (I->isDebugInstr())
175
0
      continue;
176
6.45k
177
6.45k
    // Working from the bottom, when we see a non-terminator
178
6.45k
    // instruction, we're done.
179
6.45k
    if (!isUnpredicatedTerminator(*I))
180
1.67k
      break;
181
4.78k
182
4.78k
    // A terminator that isn't a branch can't easily be handled
183
4.78k
    // by this analysis.
184
4.78k
    if (!I->isBranch())
185
1.79k
      return true;
186
2.98k
187
2.98k
    // Handle unconditional branches.
188
2.98k
    if (I->getOpcode() == BPF::JMP) {
189
797
      if (!AllowModify) {
190
496
        TBB = I->getOperand(0).getMBB();
191
496
        continue;
192
496
      }
193
301
194
301
      // If the block has any instructions after a J, delete them.
195
301
      while (std::next(I) != MBB.end())
196
0
        std::next(I)->eraseFromParent();
197
301
      Cond.clear();
198
301
      FBB = nullptr;
199
301
200
301
      // Delete the J if it's equivalent to a fall-through.
201
301
      if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
202
54
        TBB = nullptr;
203
54
        I->eraseFromParent();
204
54
        I = MBB.end();
205
54
        continue;
206
54
      }
207
247
208
247
      // TBB is used to indicate the unconditinal destination.
209
247
      TBB = I->getOperand(0).getMBB();
210
247
      continue;
211
247
    }
212
2.19k
    // Cannot handle conditional branches
213
2.19k
    return true;
214
2.19k
  }
215
5.76k
216
5.76k
  
return false1.77k
;
217
5.76k
}
218
219
unsigned BPFInstrInfo::insertBranch(MachineBasicBlock &MBB,
220
                                    MachineBasicBlock *TBB,
221
                                    MachineBasicBlock *FBB,
222
                                    ArrayRef<MachineOperand> Cond,
223
                                    const DebugLoc &DL,
224
42
                                    int *BytesAdded) const {
225
42
  assert(!BytesAdded && "code size not handled");
226
42
227
42
  // Shouldn't be a fall through.
228
42
  assert(TBB && "insertBranch must not be told to insert a fallthrough");
229
42
230
42
  if (Cond.empty()) {
231
42
    // Unconditional branch
232
42
    assert(!FBB && "Unconditional branch with multiple successors!");
233
42
    BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB);
234
42
    return 1;
235
42
  }
236
0
237
0
  llvm_unreachable("Unexpected conditional branch");
238
0
}
239
240
unsigned BPFInstrInfo::removeBranch(MachineBasicBlock &MBB,
241
45
                                    int *BytesRemoved) const {
242
45
  assert(!BytesRemoved && "code size not handled");
243
45
244
45
  MachineBasicBlock::iterator I = MBB.end();
245
45
  unsigned Count = 0;
246
45
247
89
  while (I != MBB.begin()) {
248
89
    --I;
249
89
    if (I->isDebugInstr())
250
0
      continue;
251
89
    if (I->getOpcode() != BPF::JMP)
252
45
      break;
253
44
    // Remove the branch.
254
44
    I->eraseFromParent();
255
44
    I = MBB.end();
256
44
    ++Count;
257
44
  }
258
45
259
45
  return Count;
260
45
}