Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/BPF/BPFMIPeephole.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-------------- BPFMIPeephole.cpp - MI Peephole Cleanups  -------------===//
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 pass performs peephole optimizations to cleanup ugly code sequences at
10
// MachineInstruction layer.
11
//
12
// Currently, there are two optimizations implemented:
13
//  - One pre-RA MachineSSA pass to eliminate type promotion sequences, those
14
//    zero extend 32-bit subregisters to 64-bit registers, if the compiler
15
//    could prove the subregisters is defined by 32-bit operations in which
16
//    case the upper half of the underlying 64-bit registers were zeroed
17
//    implicitly.
18
//
19
//  - One post-RA PreEmit pass to do final cleanup on some redundant
20
//    instructions generated due to bad RA on subregister.
21
//===----------------------------------------------------------------------===//
22
23
#include "BPF.h"
24
#include "BPFInstrInfo.h"
25
#include "BPFTargetMachine.h"
26
#include "llvm/ADT/Statistic.h"
27
#include "llvm/CodeGen/MachineInstrBuilder.h"
28
#include "llvm/CodeGen/MachineRegisterInfo.h"
29
30
using namespace llvm;
31
32
#define DEBUG_TYPE "bpf-mi-zext-elim"
33
34
STATISTIC(ZExtElemNum, "Number of zero extension shifts eliminated");
35
36
namespace {
37
38
struct BPFMIPeephole : public MachineFunctionPass {
39
40
  static char ID;
41
  const BPFInstrInfo *TII;
42
  MachineFunction *MF;
43
  MachineRegisterInfo *MRI;
44
45
8
  BPFMIPeephole() : MachineFunctionPass(ID) {
46
8
    initializeBPFMIPeepholePass(*PassRegistry::getPassRegistry());
47
8
  }
48
49
private:
50
  // Initialize class variables.
51
  void initialize(MachineFunction &MFParm);
52
53
  bool isMovFrom32Def(MachineInstr *MovMI);
54
  bool eliminateZExtSeq(void);
55
56
public:
57
58
  // Main entry point for this pass.
59
46
  bool runOnMachineFunction(MachineFunction &MF) override {
60
46
    if (skipFunction(MF.getFunction()))
61
0
      return false;
62
46
63
46
    initialize(MF);
64
46
65
46
    return eliminateZExtSeq();
66
46
  }
67
};
68
69
// Initialize class variables.
70
46
void BPFMIPeephole::initialize(MachineFunction &MFParm) {
71
46
  MF = &MFParm;
72
46
  MRI = &MF->getRegInfo();
73
46
  TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
74
46
  LLVM_DEBUG(dbgs() << "*** BPF MachineSSA peephole pass ***\n\n");
75
46
}
76
77
bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI)
78
11
{
79
11
  MachineInstr *DefInsn = MRI->getVRegDef(MovMI->getOperand(1).getReg());
80
11
81
11
  LLVM_DEBUG(dbgs() << "  Def of Mov Src:");
82
11
  LLVM_DEBUG(DefInsn->dump());
83
11
84
11
  if (!DefInsn)
85
0
    return false;
86
11
87
11
  if (DefInsn->isPHI()) {
88
0
    for (unsigned i = 1, e = DefInsn->getNumOperands(); i < e; i += 2) {
89
0
      MachineOperand &opnd = DefInsn->getOperand(i);
90
0
91
0
      if (!opnd.isReg())
92
0
        return false;
93
0
94
0
      MachineInstr *PhiDef = MRI->getVRegDef(opnd.getReg());
95
0
      // quick check on PHI incoming definitions.
96
0
      if (!PhiDef || PhiDef->isPHI() || PhiDef->getOpcode() == BPF::COPY)
97
0
        return false;
98
0
    }
99
0
  }
100
11
101
11
  if (DefInsn->getOpcode() == BPF::COPY) {
102
11
    MachineOperand &opnd = DefInsn->getOperand(1);
103
11
104
11
    if (!opnd.isReg())
105
0
      return false;
106
11
107
11
    unsigned Reg = opnd.getReg();
108
11
    if ((TargetRegisterInfo::isVirtualRegister(Reg) &&
109
11
         
MRI->getRegClass(Reg) == &BPF::GPRRegClass1
))
110
1
       return false;
111
10
  }
112
10
113
10
  LLVM_DEBUG(dbgs() << "  One ZExt elim sequence identified.\n");
114
10
115
10
  return true;
116
10
}
117
118
46
bool BPFMIPeephole::eliminateZExtSeq(void) {
119
46
  MachineInstr* ToErase = nullptr;
120
46
  bool Eliminated = false;
121
46
122
66
  for (MachineBasicBlock &MBB : *MF) {
123
294
    for (MachineInstr &MI : MBB) {
124
294
      // If the previous instruction was marked for elimination, remove it now.
125
294
      if (ToErase) {
126
10
        ToErase->eraseFromParent();
127
10
        ToErase = nullptr;
128
10
      }
129
294
130
294
      // Eliminate the 32-bit to 64-bit zero extension sequence when possible.
131
294
      //
132
294
      //   MOV_32_64 rB, wA
133
294
      //   SLL_ri    rB, rB, 32
134
294
      //   SRL_ri    rB, rB, 32
135
294
      if (MI.getOpcode() == BPF::SRL_ri &&
136
294
          
MI.getOperand(2).getImm() == 3211
) {
137
11
        unsigned DstReg = MI.getOperand(0).getReg();
138
11
        unsigned ShfReg = MI.getOperand(1).getReg();
139
11
        MachineInstr *SllMI = MRI->getVRegDef(ShfReg);
140
11
141
11
        LLVM_DEBUG(dbgs() << "Starting SRL found:");
142
11
        LLVM_DEBUG(MI.dump());
143
11
144
11
        if (!SllMI ||
145
11
            SllMI->isPHI() ||
146
11
            SllMI->getOpcode() != BPF::SLL_ri ||
147
11
            SllMI->getOperand(2).getImm() != 32)
148
0
          continue;
149
11
150
11
        LLVM_DEBUG(dbgs() << "  SLL found:");
151
11
        LLVM_DEBUG(SllMI->dump());
152
11
153
11
        MachineInstr *MovMI = MRI->getVRegDef(SllMI->getOperand(1).getReg());
154
11
        if (!MovMI ||
155
11
            MovMI->isPHI() ||
156
11
            MovMI->getOpcode() != BPF::MOV_32_64)
157
0
          continue;
158
11
159
11
        LLVM_DEBUG(dbgs() << "  Type cast Mov found:");
160
11
        LLVM_DEBUG(MovMI->dump());
161
11
162
11
        unsigned SubReg = MovMI->getOperand(1).getReg();
163
11
        if (!isMovFrom32Def(MovMI)) {
164
1
          LLVM_DEBUG(dbgs()
165
1
                     << "  One ZExt elim sequence failed qualifying elim.\n");
166
1
          continue;
167
1
        }
168
10
169
10
        BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::SUBREG_TO_REG), DstReg)
170
10
          .addImm(0).addReg(SubReg).addImm(BPF::sub_32);
171
10
172
10
        SllMI->eraseFromParent();
173
10
        MovMI->eraseFromParent();
174
10
        // MI is the right shift, we can't erase it in it's own iteration.
175
10
        // Mark it to ToErase, and erase in the next iteration.
176
10
        ToErase = &MI;
177
10
        ZExtElemNum++;
178
10
        Eliminated = true;
179
10
      }
180
294
    }
181
66
  }
182
46
183
46
  return Eliminated;
184
46
}
185
186
} // end default namespace
187
188
INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE,
189
                "BPF MachineSSA Peephole Optimization", false, false)
190
191
char BPFMIPeephole::ID = 0;
192
8
FunctionPass* llvm::createBPFMIPeepholePass() { return new BPFMIPeephole(); }
193
194
STATISTIC(RedundantMovElemNum, "Number of redundant moves eliminated");
195
196
namespace {
197
198
struct BPFMIPreEmitPeephole : public MachineFunctionPass {
199
200
  static char ID;
201
  MachineFunction *MF;
202
  const TargetRegisterInfo *TRI;
203
204
8
  BPFMIPreEmitPeephole() : MachineFunctionPass(ID) {
205
8
    initializeBPFMIPreEmitPeepholePass(*PassRegistry::getPassRegistry());
206
8
  }
207
208
private:
209
  // Initialize class variables.
210
  void initialize(MachineFunction &MFParm);
211
212
  bool eliminateRedundantMov(void);
213
214
public:
215
216
  // Main entry point for this pass.
217
44
  bool runOnMachineFunction(MachineFunction &MF) override {
218
44
    if (skipFunction(MF.getFunction()))
219
0
      return false;
220
44
221
44
    initialize(MF);
222
44
223
44
    return eliminateRedundantMov();
224
44
  }
225
};
226
227
// Initialize class variables.
228
44
void BPFMIPreEmitPeephole::initialize(MachineFunction &MFParm) {
229
44
  MF = &MFParm;
230
44
  TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
231
44
  LLVM_DEBUG(dbgs() << "*** BPF PreEmit peephole pass ***\n\n");
232
44
}
233
234
44
bool BPFMIPreEmitPeephole::eliminateRedundantMov(void) {
235
44
  MachineInstr* ToErase = nullptr;
236
44
  bool Eliminated = false;
237
44
238
64
  for (MachineBasicBlock &MBB : *MF) {
239
155
    for (MachineInstr &MI : MBB) {
240
155
      // If the previous instruction was marked for elimination, remove it now.
241
155
      if (ToErase) {
242
2
        LLVM_DEBUG(dbgs() << "  Redundant Mov Eliminated:");
243
2
        LLVM_DEBUG(ToErase->dump());
244
2
        ToErase->eraseFromParent();
245
2
        ToErase = nullptr;
246
2
      }
247
155
248
155
      // Eliminate identical move:
249
155
      //
250
155
      //   MOV rA, rA
251
155
      //
252
155
      // This is particularly possible to happen when sub-register support
253
155
      // enabled. The special type cast insn MOV_32_64 involves different
254
155
      // register class on src (i32) and dst (i64), RA could generate useless
255
155
      // instruction due to this.
256
155
      if (MI.getOpcode() == BPF::MOV_32_64) {
257
3
        unsigned dst = MI.getOperand(0).getReg();
258
3
        unsigned dst_sub = TRI->getSubReg(dst, BPF::sub_32);
259
3
        unsigned src = MI.getOperand(1).getReg();
260
3
261
3
        if (dst_sub != src)
262
1
          continue;
263
2
264
2
        ToErase = &MI;
265
2
        RedundantMovElemNum++;
266
2
        Eliminated = true;
267
2
      }
268
155
    }
269
64
  }
270
44
271
44
  return Eliminated;
272
44
}
273
274
} // end default namespace
275
276
INITIALIZE_PASS(BPFMIPreEmitPeephole, "bpf-mi-pemit-peephole",
277
                "BPF PreEmit Peephole Optimization", false, false)
278
279
char BPFMIPreEmitPeephole::ID = 0;
280
FunctionPass* llvm::createBPFMIPreEmitPeepholePass()
281
8
{
282
8
  return new BPFMIPreEmitPeephole();
283
8
}