blob: 3df14b4ad5b8a4b602e5231ebf18460396981aa2 [file] [log] [blame]
Yonghong Song60fed1f2018-02-23 23:49:32 +00001//===-------------- BPFMIPeephole.cpp - MI Peephole Cleanups -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This pass performs peephole optimizations to cleanup ugly code sequences at
11// MachineInstruction layer.
12//
13// Currently, the only optimization in this pass is to eliminate type promotion
14// sequences, those zero extend 32-bit subregisters to 64-bit registers, if the
15// compiler could prove the subregisters is defined by 32-bit operations in
16// which case the upper half of the underlying 64-bit registers were zeroed
17// implicitly.
18//
19//===----------------------------------------------------------------------===//
20
21#include "BPF.h"
22#include "BPFInstrInfo.h"
23#include "BPFTargetMachine.h"
24#include "llvm/ADT/Statistic.h"
25#include "llvm/CodeGen/MachineInstrBuilder.h"
26#include "llvm/CodeGen/MachineRegisterInfo.h"
27
28using namespace llvm;
29
30#define DEBUG_TYPE "bpf-mi-promotion-elim"
31
32STATISTIC(CmpPromotionElemNum, "Number of shifts for CMP promotion eliminated");
33
34namespace {
35
36struct BPFMIPeephole : public MachineFunctionPass {
37
38 static char ID;
39 const BPFInstrInfo *TII;
40 MachineFunction *MF;
41 MachineRegisterInfo *MRI;
42
43 BPFMIPeephole() : MachineFunctionPass(ID) {
44 initializeBPFMIPeepholePass(*PassRegistry::getPassRegistry());
45 }
46
47private:
48 // Initialize class variables.
49 void initialize(MachineFunction &MFParm);
50
51 bool eliminateCmpPromotionSeq(void);
52 MachineInstr *getInsnDefZExtSubReg(unsigned Reg) const;
53 void updateInsnSeq(MachineBasicBlock &MBB, MachineInstr &MI,
54 unsigned Reg) const;
55
56public:
57
58 // Main entry point for this pass.
59 bool runOnMachineFunction(MachineFunction &MF) override {
60 if (skipFunction(MF.getFunction()))
61 return false;
62
63 initialize(MF);
64
65 return eliminateCmpPromotionSeq();
66 }
67};
68
69// Initialize class variables.
70void BPFMIPeephole::initialize(MachineFunction &MFParm) {
71 MF = &MFParm;
72 MRI = &MF->getRegInfo();
73 TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
74 DEBUG(dbgs() << "*** BPF MI peephole pass ***\n\n");
75}
76
77MachineInstr *BPFMIPeephole::getInsnDefZExtSubReg(unsigned Reg) const {
78 MachineInstr *Insn = MRI->getVRegDef(Reg);
79
80 if (!Insn ||
81 Insn->isPHI() ||
82 Insn->getOpcode() != BPF::SRL_ri ||
83 Insn->getOperand(2).getImm() != 32)
84 return nullptr;
85
86 Insn = MRI->getVRegDef(Insn->getOperand(1).getReg());
87 if (!Insn ||
88 Insn->isPHI() ||
89 Insn->getOpcode() != BPF::SLL_ri ||
90 Insn->getOperand(2).getImm() != 32)
91 return nullptr;
92
93 Insn = MRI->getVRegDef(Insn->getOperand(1).getReg());
94 if (!Insn ||
95 Insn->isPHI() ||
96 Insn->getOpcode() != BPF::MOV_32_64)
97 return nullptr;
98
Yonghong Song89e47ac2018-03-13 06:47:00 +000099 Insn = MRI->getVRegDef(Insn->getOperand(1).getReg());
100 if (!Insn || Insn->isPHI())
101 return nullptr;
102
103 if (Insn->getOpcode() == BPF::COPY) {
104 MachineOperand &opnd = Insn->getOperand(1);
105
106 if (!opnd.isReg())
107 return nullptr;
108
109 unsigned Reg = opnd.getReg();
110 if ((TargetRegisterInfo::isVirtualRegister(Reg) &&
111 MRI->getRegClass(Reg) == &BPF::GPRRegClass) ||
112 (TargetRegisterInfo::isPhysicalRegister(Reg) &&
113 BPF::GPRRegClass.contains(Reg)))
114 return nullptr;
115 }
116
Yonghong Song60fed1f2018-02-23 23:49:32 +0000117 return Insn;
118}
119
120void
121BPFMIPeephole::updateInsnSeq(MachineBasicBlock &MBB, MachineInstr &MI,
122 unsigned Reg) const {
123 MachineInstr *Mov, *Lshift, *Rshift;
124 unsigned SubReg;
125 DebugLoc DL;
126
127 Rshift = MRI->getVRegDef(Reg);
128 Lshift = MRI->getVRegDef(Rshift->getOperand(1).getReg());
129 Mov = MRI->getVRegDef(Lshift->getOperand(1).getReg());
130 SubReg = Mov->getOperand(1).getReg();
131 DL = MI.getDebugLoc();
132 BuildMI(MBB, Rshift, DL, TII->get(BPF::SUBREG_TO_REG), Reg)
133 .addImm(0).addReg(SubReg).addImm(BPF::sub_32);
134 Rshift->eraseFromParent();
135 Lshift->eraseFromParent();
136 Mov->eraseFromParent();
137
138 CmpPromotionElemNum++;
139}
140
141bool BPFMIPeephole::eliminateCmpPromotionSeq(void) {
142 bool Eliminated = false;
143 MachineInstr *Mov;
144 unsigned Reg;
145
146 for (MachineBasicBlock &MBB : *MF) {
147 for (MachineInstr &MI : MBB) {
148 switch (MI.getOpcode()) {
149 default:
150 break;
151 case BPF::JUGT_rr:
152 case BPF::JUGE_rr:
153 case BPF::JULT_rr:
154 case BPF::JULE_rr:
155 case BPF::JEQ_rr:
156 case BPF::JNE_rr:
157 Reg = MI.getOperand(1).getReg();
158 Mov = getInsnDefZExtSubReg(Reg);
159 if (!Mov)
160 break;
161
162 updateInsnSeq(MBB, MI, Reg);
163 Eliminated = true;
164
165 // Fallthrough
166 case BPF::JUGT_ri:
167 case BPF::JUGE_ri:
168 case BPF::JULT_ri:
169 case BPF::JULE_ri:
170 case BPF::JEQ_ri:
171 case BPF::JNE_ri:
172 Reg = MI.getOperand(0).getReg();
173 Mov = getInsnDefZExtSubReg(Reg);
174 if (!Mov)
175 break;
176
177 updateInsnSeq(MBB, MI, Reg);
178 Eliminated = true;
179 break;
180 }
181 }
182 }
183
184 return Eliminated;
185}
186
187} // end default namespace
188
189INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE, "BPF MI Peephole Optimization",
190 false, false)
191
192char BPFMIPeephole::ID = 0;
193FunctionPass* llvm::createBPFMIPeepholePass() { return new BPFMIPeephole(); }