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)
80     return false;
81 
82   if (DefInsn->isPHI()) {
83     for (unsigned i = 1, e = DefInsn->getNumOperands(); i < e; i += 2) {
84       MachineOperand &opnd = DefInsn->getOperand(i);
85 
86       if (!opnd.isReg())
87         return false;
88 
89       MachineInstr *PhiDef = MRI->getVRegDef(opnd.getReg());
90       // quick check on PHI incoming definitions.
91       if (!PhiDef || PhiDef->isPHI() || PhiDef->getOpcode() == BPF::COPY)
92         return false;
93     }
94   }
95 
96   if (DefInsn->getOpcode() == BPF::COPY) {
97     MachineOperand &opnd = DefInsn->getOperand(1);
98 
99     if (!opnd.isReg())
100       return false;
101 
102     unsigned Reg = opnd.getReg();
103     if ((TargetRegisterInfo::isVirtualRegister(Reg) &&
104          MRI->getRegClass(Reg) == &BPF::GPRRegClass))
105        return false;
106   }
107 
108   return true;
109 }
110 
111 bool BPFMIPeephole::eliminateZExtSeq(void) {
112   MachineInstr* ToErase = nullptr;
113   bool Eliminated = false;
114 
115   for (MachineBasicBlock &MBB : *MF) {
116     for (MachineInstr &MI : MBB) {
117       // If the previous instruction was marked for elimination, remove it now.
118       if (ToErase) {
119         ToErase->eraseFromParent();
120         ToErase = nullptr;
121       }
122 
123       // Eliminate the 32-bit to 64-bit zero extension sequence when possible.
124       //
125       //   MOV_32_64 rB, wA
126       //   SLL_ri    rB, rB, 32
127       //   SRL_ri    rB, rB, 32
128       if (MI.getOpcode() == BPF::SRL_ri &&
129           MI.getOperand(2).getImm() == 32) {
130         unsigned DstReg = MI.getOperand(0).getReg();
131         unsigned ShfReg = MI.getOperand(1).getReg();
132         MachineInstr *SllMI = MRI->getVRegDef(ShfReg);
133 
134         if (!SllMI ||
135             SllMI->isPHI() ||
136             SllMI->getOpcode() != BPF::SLL_ri ||
137             SllMI->getOperand(2).getImm() != 32)
138           continue;
139 
140         MachineInstr *MovMI = MRI->getVRegDef(SllMI->getOperand(1).getReg());
141         if (!MovMI ||
142             MovMI->isPHI() ||
143             MovMI->getOpcode() != BPF::MOV_32_64)
144           continue;
145 
146         unsigned SubReg = MovMI->getOperand(1).getReg();
147         if (!isMovFrom32Def(MovMI))
148           continue;
149 
150         BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::SUBREG_TO_REG), DstReg)
151           .addImm(0).addReg(SubReg).addImm(BPF::sub_32);
152 
153         SllMI->eraseFromParent();
154         MovMI->eraseFromParent();
155         // MI is the right shift, we can't erase it in it's own iteration.
156         // Mark it to ToErase, and erase in the next iteration.
157         ToErase = &MI;
158         ZExtElemNum++;
159         Eliminated = true;
160       }
161     }
162   }
163 
164   return Eliminated;
165 }
166 
167 } // end default namespace
168 
169 INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE, "BPF MI Peephole Optimization",
170                 false, false)
171 
172 char BPFMIPeephole::ID = 0;
173 FunctionPass* llvm::createBPFMIPeepholePass() { return new BPFMIPeephole(); }
174