1 //===-------------- BPFMIPeephole.cpp - MI Peephole Cleanups -------------===//
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
7 //===----------------------------------------------------------------------===//
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
19 // - One post-RA PreEmit pass to do final cleanup on some redundant
20 // instructions generated due to bad RA on subregister.
21 //===----------------------------------------------------------------------===//
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"
32 #define DEBUG_TYPE "bpf-mi-zext-elim"
34 STATISTIC(ZExtElemNum
, "Number of zero extension shifts eliminated");
38 struct BPFMIPeephole
: public MachineFunctionPass
{
41 const BPFInstrInfo
*TII
;
43 MachineRegisterInfo
*MRI
;
45 BPFMIPeephole() : MachineFunctionPass(ID
) {
46 initializeBPFMIPeepholePass(*PassRegistry::getPassRegistry());
50 // Initialize class variables.
51 void initialize(MachineFunction
&MFParm
);
53 bool isMovFrom32Def(MachineInstr
*MovMI
);
54 bool eliminateZExtSeq(void);
58 // Main entry point for this pass.
59 bool runOnMachineFunction(MachineFunction
&MF
) override
{
60 if (skipFunction(MF
.getFunction()))
65 return eliminateZExtSeq();
69 // Initialize class variables.
70 void BPFMIPeephole::initialize(MachineFunction
&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());
87 if (DefInsn
->isPHI()) {
88 for (unsigned i
= 1, e
= DefInsn
->getNumOperands(); i
< e
; i
+= 2) {
89 MachineOperand
&opnd
= DefInsn
->getOperand(i
);
94 MachineInstr
*PhiDef
= MRI
->getVRegDef(opnd
.getReg());
95 // quick check on PHI incoming definitions.
96 if (!PhiDef
|| PhiDef
->isPHI() || PhiDef
->getOpcode() == BPF::COPY
)
101 if (DefInsn
->getOpcode() == BPF::COPY
) {
102 MachineOperand
&opnd
= DefInsn
->getOperand(1);
107 Register Reg
= opnd
.getReg();
108 if ((Register::isVirtualRegister(Reg
) &&
109 MRI
->getRegClass(Reg
) == &BPF::GPRRegClass
))
113 LLVM_DEBUG(dbgs() << " One ZExt elim sequence identified.\n");
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.
126 ToErase
->eraseFromParent();
130 // Eliminate the 32-bit to 64-bit zero extension sequence when possible.
135 if (MI
.getOpcode() == BPF::SRL_ri
&&
136 MI
.getOperand(2).getImm() == 32) {
137 Register DstReg
= MI
.getOperand(0).getReg();
138 Register ShfReg
= MI
.getOperand(1).getReg();
139 MachineInstr
*SllMI
= MRI
->getVRegDef(ShfReg
);
141 LLVM_DEBUG(dbgs() << "Starting SRL found:");
142 LLVM_DEBUG(MI
.dump());
146 SllMI
->getOpcode() != BPF::SLL_ri
||
147 SllMI
->getOperand(2).getImm() != 32)
150 LLVM_DEBUG(dbgs() << " SLL found:");
151 LLVM_DEBUG(SllMI
->dump());
153 MachineInstr
*MovMI
= MRI
->getVRegDef(SllMI
->getOperand(1).getReg());
156 MovMI
->getOpcode() != BPF::MOV_32_64
)
159 LLVM_DEBUG(dbgs() << " Type cast Mov found:");
160 LLVM_DEBUG(MovMI
->dump());
162 Register SubReg
= MovMI
->getOperand(1).getReg();
163 if (!isMovFrom32Def(MovMI
)) {
165 << " One ZExt elim sequence failed qualifying elim.\n");
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.
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");
198 struct BPFMIPreEmitPeephole
: public MachineFunctionPass
{
202 const TargetRegisterInfo
*TRI
;
204 BPFMIPreEmitPeephole() : MachineFunctionPass(ID
) {
205 initializeBPFMIPreEmitPeepholePass(*PassRegistry::getPassRegistry());
209 // Initialize class variables.
210 void initialize(MachineFunction
&MFParm
);
212 bool eliminateRedundantMov(void);
216 // Main entry point for this pass.
217 bool runOnMachineFunction(MachineFunction
&MF
) override
{
218 if (skipFunction(MF
.getFunction()))
223 return eliminateRedundantMov();
227 // Initialize class variables.
228 void BPFMIPreEmitPeephole::initialize(MachineFunction
&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.
242 LLVM_DEBUG(dbgs() << " Redundant Mov Eliminated:");
243 LLVM_DEBUG(ToErase
->dump());
244 ToErase
->eraseFromParent();
248 // Eliminate identical move:
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 Register dst
= MI
.getOperand(0).getReg();
258 Register dst_sub
= TRI
->getSubReg(dst
, BPF::sub_32
);
259 Register src
= MI
.getOperand(1).getReg();
265 RedundantMovElemNum
++;
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();