1 //===-------------- 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 
28 using namespace llvm;
29 
30 #define DEBUG_TYPE "bpf-mi-zext-elim"
31 
32 STATISTIC(ZExtElemNum, "Number of zero extension shifts eliminated");
33 
34 namespace {
35 
36 struct 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 
47 private:
48   // Initialize class variables.
49   void initialize(MachineFunction &MFParm);
50 
51   bool isMovFrom32Def(MachineInstr *MovMI);
52   bool eliminateZExtSeq(void);
53 
54 public:
55 
56   // Main entry point for this pass.
57   bool runOnMachineFunction(MachineFunction &MF) override {
58     if (skipFunction(MF.getFunction()))
59       return false;
60 
61     initialize(MF);
62 
63     return eliminateZExtSeq();
64   }
65 };
66 
67 // Initialize class variables.
68 void BPFMIPeephole::initialize(MachineFunction &MFParm) {
69   MF = &MFParm;
70   MRI = &MF->getRegInfo();
71   TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
72   DEBUG(dbgs() << "*** BPF MI peephole pass ***\n\n");
73 }
74 
75 bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI)
76 {
77   MachineInstr *DefInsn = MRI->getVRegDef(MovMI->getOperand(1).getReg());
78 
79   if (!DefInsn || DefInsn->isPHI())
80     return false;
81 
82   if (DefInsn->getOpcode() == BPF::COPY) {
83     MachineOperand &opnd = DefInsn->getOperand(1);
84 
85     if (!opnd.isReg())
86       return false;
87 
88     unsigned Reg = opnd.getReg();
89     if ((TargetRegisterInfo::isVirtualRegister(Reg) &&
90          MRI->getRegClass(Reg) == &BPF::GPRRegClass))
91        return false;
92   }
93 
94   return true;
95 }
96 
97 bool BPFMIPeephole::eliminateZExtSeq(void) {
98   MachineInstr* ToErase = nullptr;
99   bool Eliminated = false;
100 
101   for (MachineBasicBlock &MBB : *MF) {
102     for (MachineInstr &MI : MBB) {
103       // If the previous instruction was marked for elimination, remove it now.
104       if (ToErase) {
105         ToErase->eraseFromParent();
106         ToErase = nullptr;
107       }
108 
109       // Eliminate the 32-bit to 64-bit zero extension sequence when possible.
110       //
111       //   MOV_32_64 rB, wA
112       //   SLL_ri    rB, rB, 32
113       //   SRL_ri    rB, rB, 32
114       if (MI.getOpcode() == BPF::SRL_ri &&
115           MI.getOperand(2).getImm() == 32) {
116         unsigned DstReg = MI.getOperand(0).getReg();
117         unsigned ShfReg = MI.getOperand(1).getReg();
118         MachineInstr *SllMI = MRI->getVRegDef(ShfReg);
119 
120         if (!SllMI ||
121             SllMI->isPHI() ||
122             SllMI->getOpcode() != BPF::SLL_ri ||
123             SllMI->getOperand(2).getImm() != 32)
124           continue;
125 
126         MachineInstr *MovMI = MRI->getVRegDef(SllMI->getOperand(1).getReg());
127         if (!MovMI ||
128             MovMI->isPHI() ||
129             MovMI->getOpcode() != BPF::MOV_32_64)
130           continue;
131 
132         if (!isMovFrom32Def(MovMI))
133           continue;
134 
135         unsigned SubReg = MovMI->getOperand(1).getReg();
136         BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::SUBREG_TO_REG), DstReg)
137           .addImm(0).addReg(SubReg).addImm(BPF::sub_32);
138 
139         SllMI->eraseFromParent();
140         MovMI->eraseFromParent();
141         // MI is the right shift, we can't erase it in it's own iteration.
142         // Mark it to ToErase, and erase in the next iteration.
143         ToErase = &MI;
144         ZExtElemNum++;
145         Eliminated = true;
146       }
147     }
148   }
149 
150   return Eliminated;
151 }
152 
153 } // end default namespace
154 
155 INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE, "BPF MI Peephole Optimization",
156                 false, false)
157 
158 char BPFMIPeephole::ID = 0;
159 FunctionPass* llvm::createBPFMIPeepholePass() { return new BPFMIPeephole(); }
160