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, there are two optimizations implemented: 14 // - One pre-RA MachineSSA pass to eliminate type promotion sequences, those 15 // zero extend 32-bit subregisters to 64-bit registers, if the compiler 16 // could prove the subregisters is defined by 32-bit operations in which 17 // case the upper half of the underlying 64-bit registers were zeroed 18 // implicitly. 19 // 20 // - One post-RA PreEmit pass to do final cleanup on some redundant 21 // instructions generated due to bad RA on subregister. 22 //===----------------------------------------------------------------------===// 23 24 #include "BPF.h" 25 #include "BPFInstrInfo.h" 26 #include "BPFTargetMachine.h" 27 #include "llvm/ADT/Statistic.h" 28 #include "llvm/CodeGen/MachineInstrBuilder.h" 29 #include "llvm/CodeGen/MachineRegisterInfo.h" 30 31 using namespace llvm; 32 33 #define DEBUG_TYPE "bpf-mi-zext-elim" 34 35 STATISTIC(ZExtElemNum, "Number of zero extension shifts eliminated"); 36 37 namespace { 38 39 struct BPFMIPeephole : public MachineFunctionPass { 40 41 static char ID; 42 const BPFInstrInfo *TII; 43 MachineFunction *MF; 44 MachineRegisterInfo *MRI; 45 46 BPFMIPeephole() : MachineFunctionPass(ID) { 47 initializeBPFMIPeepholePass(*PassRegistry::getPassRegistry()); 48 } 49 50 private: 51 // Initialize class variables. 52 void initialize(MachineFunction &MFParm); 53 54 bool isMovFrom32Def(MachineInstr *MovMI); 55 bool eliminateZExtSeq(void); 56 57 public: 58 59 // Main entry point for this pass. 60 bool runOnMachineFunction(MachineFunction &MF) override { 61 if (skipFunction(MF.getFunction())) 62 return false; 63 64 initialize(MF); 65 66 return eliminateZExtSeq(); 67 } 68 }; 69 70 // Initialize class variables. 71 void BPFMIPeephole::initialize(MachineFunction &MFParm) { 72 MF = &MFParm; 73 MRI = &MF->getRegInfo(); 74 TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo(); 75 DEBUG(dbgs() << "*** BPF MachineSSA peephole pass ***\n\n"); 76 } 77 78 bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI) 79 { 80 MachineInstr *DefInsn = MRI->getVRegDef(MovMI->getOperand(1).getReg()); 81 82 DEBUG(dbgs() << " Def of Mov Src:"); 83 DEBUG(DefInsn->dump()); 84 85 if (!DefInsn) 86 return false; 87 88 if (DefInsn->isPHI()) { 89 for (unsigned i = 1, e = DefInsn->getNumOperands(); i < e; i += 2) { 90 MachineOperand &opnd = DefInsn->getOperand(i); 91 92 if (!opnd.isReg()) 93 return false; 94 95 MachineInstr *PhiDef = MRI->getVRegDef(opnd.getReg()); 96 // quick check on PHI incoming definitions. 97 if (!PhiDef || PhiDef->isPHI() || PhiDef->getOpcode() == BPF::COPY) 98 return false; 99 } 100 } 101 102 if (DefInsn->getOpcode() == BPF::COPY) { 103 MachineOperand &opnd = DefInsn->getOperand(1); 104 105 if (!opnd.isReg()) 106 return false; 107 108 unsigned Reg = opnd.getReg(); 109 if ((TargetRegisterInfo::isVirtualRegister(Reg) && 110 MRI->getRegClass(Reg) == &BPF::GPRRegClass)) 111 return false; 112 } 113 114 DEBUG(dbgs() << " One ZExt elim sequence identified.\n"); 115 116 return true; 117 } 118 119 bool BPFMIPeephole::eliminateZExtSeq(void) { 120 MachineInstr* ToErase = nullptr; 121 bool Eliminated = false; 122 123 for (MachineBasicBlock &MBB : *MF) { 124 for (MachineInstr &MI : MBB) { 125 // If the previous instruction was marked for elimination, remove it now. 126 if (ToErase) { 127 ToErase->eraseFromParent(); 128 ToErase = nullptr; 129 } 130 131 // Eliminate the 32-bit to 64-bit zero extension sequence when possible. 132 // 133 // MOV_32_64 rB, wA 134 // SLL_ri rB, rB, 32 135 // SRL_ri rB, rB, 32 136 if (MI.getOpcode() == BPF::SRL_ri && 137 MI.getOperand(2).getImm() == 32) { 138 unsigned DstReg = MI.getOperand(0).getReg(); 139 unsigned ShfReg = MI.getOperand(1).getReg(); 140 MachineInstr *SllMI = MRI->getVRegDef(ShfReg); 141 142 DEBUG(dbgs() << "Starting SRL found:"); 143 DEBUG(MI.dump()); 144 145 if (!SllMI || 146 SllMI->isPHI() || 147 SllMI->getOpcode() != BPF::SLL_ri || 148 SllMI->getOperand(2).getImm() != 32) 149 continue; 150 151 DEBUG(dbgs() << " SLL found:"); 152 DEBUG(SllMI->dump()); 153 154 MachineInstr *MovMI = MRI->getVRegDef(SllMI->getOperand(1).getReg()); 155 if (!MovMI || 156 MovMI->isPHI() || 157 MovMI->getOpcode() != BPF::MOV_32_64) 158 continue; 159 160 DEBUG(dbgs() << " Type cast Mov found:"); 161 DEBUG(MovMI->dump()); 162 163 unsigned SubReg = MovMI->getOperand(1).getReg(); 164 if (!isMovFrom32Def(MovMI)) { 165 DEBUG(dbgs() << " One ZExt elim sequence failed qualifying elim.\n"); 166 continue; 167 } 168 169 BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::SUBREG_TO_REG), DstReg) 170 .addImm(0).addReg(SubReg).addImm(BPF::sub_32); 171 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; 179 } 180 } 181 } 182 183 return Eliminated; 184 } 185 186 } // end default namespace 187 188 INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE, 189 "BPF MachineSSA Peephole Optimization", false, false) 190 191 char BPFMIPeephole::ID = 0; 192 FunctionPass* llvm::createBPFMIPeepholePass() { return new BPFMIPeephole(); } 193 194 STATISTIC(RedundantMovElemNum, "Number of redundant moves eliminated"); 195 196 namespace { 197 198 struct BPFMIPreEmitPeephole : public MachineFunctionPass { 199 200 static char ID; 201 MachineFunction *MF; 202 const TargetRegisterInfo *TRI; 203 204 BPFMIPreEmitPeephole() : MachineFunctionPass(ID) { 205 initializeBPFMIPreEmitPeepholePass(*PassRegistry::getPassRegistry()); 206 } 207 208 private: 209 // Initialize class variables. 210 void initialize(MachineFunction &MFParm); 211 212 bool eliminateRedundantMov(void); 213 214 public: 215 216 // Main entry point for this pass. 217 bool runOnMachineFunction(MachineFunction &MF) override { 218 if (skipFunction(MF.getFunction())) 219 return false; 220 221 initialize(MF); 222 223 return eliminateRedundantMov(); 224 } 225 }; 226 227 // Initialize class variables. 228 void BPFMIPreEmitPeephole::initialize(MachineFunction &MFParm) { 229 MF = &MFParm; 230 TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo(); 231 DEBUG(dbgs() << "*** BPF PreEmit peephole pass ***\n\n"); 232 } 233 234 bool BPFMIPreEmitPeephole::eliminateRedundantMov(void) { 235 MachineInstr* ToErase = nullptr; 236 bool Eliminated = false; 237 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 DEBUG(dbgs() << " Redundant Mov Eliminated:"); 243 DEBUG(ToErase->dump()); 244 ToErase->eraseFromParent(); 245 ToErase = nullptr; 246 } 247 248 // Eliminate identical move: 249 // 250 // MOV rA, rA 251 // 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(); 260 261 if (dst_sub != src) 262 continue; 263 264 ToErase = &MI; 265 RedundantMovElemNum++; 266 Eliminated = true; 267 } 268 } 269 } 270 271 return Eliminated; 272 } 273 274 } // end default namespace 275 276 INITIALIZE_PASS(BPFMIPreEmitPeephole, "bpf-mi-pemit-peephole", 277 "BPF PreEmit Peephole Optimization", false, false) 278 279 char BPFMIPreEmitPeephole::ID = 0; 280 FunctionPass* llvm::createBPFMIPreEmitPeepholePass() 281 { 282 return new BPFMIPreEmitPeephole(); 283 } 284