[ARM] MVE integer min and max
[llvm-core.git] / lib / Target / BPF / BPFMIPeephole.cpp
blob156ba793e35921b50b3c9eabea11cdd3f26ae849
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.
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.
19 // - One post-RA PreEmit pass to do final cleanup on some redundant
20 // instructions generated due to bad RA on subregister.
21 //===----------------------------------------------------------------------===//
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"
30 using namespace llvm;
32 #define DEBUG_TYPE "bpf-mi-zext-elim"
34 STATISTIC(ZExtElemNum, "Number of zero extension shifts eliminated");
36 namespace {
38 struct BPFMIPeephole : public MachineFunctionPass {
40 static char ID;
41 const BPFInstrInfo *TII;
42 MachineFunction *MF;
43 MachineRegisterInfo *MRI;
45 BPFMIPeephole() : MachineFunctionPass(ID) {
46 initializeBPFMIPeepholePass(*PassRegistry::getPassRegistry());
49 private:
50 // Initialize class variables.
51 void initialize(MachineFunction &MFParm);
53 bool isMovFrom32Def(MachineInstr *MovMI);
54 bool eliminateZExtSeq(void);
56 public:
58 // Main entry point for this pass.
59 bool runOnMachineFunction(MachineFunction &MF) override {
60 if (skipFunction(MF.getFunction()))
61 return false;
63 initialize(MF);
65 return eliminateZExtSeq();
69 // Initialize class variables.
70 void BPFMIPeephole::initialize(MachineFunction &MFParm) {
71 MF = &MFParm;
72 MRI = &MF->getRegInfo();
73 TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
74 LLVM_DEBUG(dbgs() << "*** BPF MachineSSA peephole pass ***\n\n");
77 bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI)
79 MachineInstr *DefInsn = MRI->getVRegDef(MovMI->getOperand(1).getReg());
81 LLVM_DEBUG(dbgs() << " Def of Mov Src:");
82 LLVM_DEBUG(DefInsn->dump());
84 if (!DefInsn)
85 return false;
87 if (DefInsn->isPHI()) {
88 for (unsigned i = 1, e = DefInsn->getNumOperands(); i < e; i += 2) {
89 MachineOperand &opnd = DefInsn->getOperand(i);
91 if (!opnd.isReg())
92 return false;
94 MachineInstr *PhiDef = MRI->getVRegDef(opnd.getReg());
95 // quick check on PHI incoming definitions.
96 if (!PhiDef || PhiDef->isPHI() || PhiDef->getOpcode() == BPF::COPY)
97 return false;
101 if (DefInsn->getOpcode() == BPF::COPY) {
102 MachineOperand &opnd = DefInsn->getOperand(1);
104 if (!opnd.isReg())
105 return false;
107 unsigned Reg = opnd.getReg();
108 if ((TargetRegisterInfo::isVirtualRegister(Reg) &&
109 MRI->getRegClass(Reg) == &BPF::GPRRegClass))
110 return false;
113 LLVM_DEBUG(dbgs() << " One ZExt elim sequence identified.\n");
115 return true;
118 bool BPFMIPeephole::eliminateZExtSeq(void) {
119 MachineInstr* ToErase = nullptr;
120 bool Eliminated = false;
122 for (MachineBasicBlock &MBB : *MF) {
123 for (MachineInstr &MI : MBB) {
124 // If the previous instruction was marked for elimination, remove it now.
125 if (ToErase) {
126 ToErase->eraseFromParent();
127 ToErase = nullptr;
130 // Eliminate the 32-bit to 64-bit zero extension sequence when possible.
132 // MOV_32_64 rB, wA
133 // SLL_ri rB, rB, 32
134 // SRL_ri rB, rB, 32
135 if (MI.getOpcode() == BPF::SRL_ri &&
136 MI.getOperand(2).getImm() == 32) {
137 unsigned DstReg = MI.getOperand(0).getReg();
138 unsigned ShfReg = MI.getOperand(1).getReg();
139 MachineInstr *SllMI = MRI->getVRegDef(ShfReg);
141 LLVM_DEBUG(dbgs() << "Starting SRL found:");
142 LLVM_DEBUG(MI.dump());
144 if (!SllMI ||
145 SllMI->isPHI() ||
146 SllMI->getOpcode() != BPF::SLL_ri ||
147 SllMI->getOperand(2).getImm() != 32)
148 continue;
150 LLVM_DEBUG(dbgs() << " SLL found:");
151 LLVM_DEBUG(SllMI->dump());
153 MachineInstr *MovMI = MRI->getVRegDef(SllMI->getOperand(1).getReg());
154 if (!MovMI ||
155 MovMI->isPHI() ||
156 MovMI->getOpcode() != BPF::MOV_32_64)
157 continue;
159 LLVM_DEBUG(dbgs() << " Type cast Mov found:");
160 LLVM_DEBUG(MovMI->dump());
162 unsigned SubReg = MovMI->getOperand(1).getReg();
163 if (!isMovFrom32Def(MovMI)) {
164 LLVM_DEBUG(dbgs()
165 << " One ZExt elim sequence failed qualifying elim.\n");
166 continue;
169 BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::SUBREG_TO_REG), DstReg)
170 .addImm(0).addReg(SubReg).addImm(BPF::sub_32);
172 SllMI->eraseFromParent();
173 MovMI->eraseFromParent();
174 // MI is the right shift, we can't erase it in it's own iteration.
175 // Mark it to ToErase, and erase in the next iteration.
176 ToErase = &MI;
177 ZExtElemNum++;
178 Eliminated = true;
183 return Eliminated;
186 } // end default namespace
188 INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE,
189 "BPF MachineSSA Peephole Optimization", false, false)
191 char BPFMIPeephole::ID = 0;
192 FunctionPass* llvm::createBPFMIPeepholePass() { return new BPFMIPeephole(); }
194 STATISTIC(RedundantMovElemNum, "Number of redundant moves eliminated");
196 namespace {
198 struct BPFMIPreEmitPeephole : public MachineFunctionPass {
200 static char ID;
201 MachineFunction *MF;
202 const TargetRegisterInfo *TRI;
204 BPFMIPreEmitPeephole() : MachineFunctionPass(ID) {
205 initializeBPFMIPreEmitPeepholePass(*PassRegistry::getPassRegistry());
208 private:
209 // Initialize class variables.
210 void initialize(MachineFunction &MFParm);
212 bool eliminateRedundantMov(void);
214 public:
216 // Main entry point for this pass.
217 bool runOnMachineFunction(MachineFunction &MF) override {
218 if (skipFunction(MF.getFunction()))
219 return false;
221 initialize(MF);
223 return eliminateRedundantMov();
227 // Initialize class variables.
228 void BPFMIPreEmitPeephole::initialize(MachineFunction &MFParm) {
229 MF = &MFParm;
230 TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
231 LLVM_DEBUG(dbgs() << "*** BPF PreEmit peephole pass ***\n\n");
234 bool BPFMIPreEmitPeephole::eliminateRedundantMov(void) {
235 MachineInstr* ToErase = nullptr;
236 bool Eliminated = false;
238 for (MachineBasicBlock &MBB : *MF) {
239 for (MachineInstr &MI : MBB) {
240 // If the previous instruction was marked for elimination, remove it now.
241 if (ToErase) {
242 LLVM_DEBUG(dbgs() << " Redundant Mov Eliminated:");
243 LLVM_DEBUG(ToErase->dump());
244 ToErase->eraseFromParent();
245 ToErase = nullptr;
248 // Eliminate identical move:
250 // MOV rA, rA
252 // This is particularly possible to happen when sub-register support
253 // enabled. The special type cast insn MOV_32_64 involves different
254 // register class on src (i32) and dst (i64), RA could generate useless
255 // instruction due to this.
256 if (MI.getOpcode() == BPF::MOV_32_64) {
257 unsigned dst = MI.getOperand(0).getReg();
258 unsigned dst_sub = TRI->getSubReg(dst, BPF::sub_32);
259 unsigned src = MI.getOperand(1).getReg();
261 if (dst_sub != src)
262 continue;
264 ToErase = &MI;
265 RedundantMovElemNum++;
266 Eliminated = true;
271 return Eliminated;
274 } // end default namespace
276 INITIALIZE_PASS(BPFMIPreEmitPeephole, "bpf-mi-pemit-peephole",
277 "BPF PreEmit Peephole Optimization", false, false)
279 char BPFMIPreEmitPeephole::ID = 0;
280 FunctionPass* llvm::createBPFMIPreEmitPeepholePass()
282 return new BPFMIPreEmitPeephole();