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-promotion-elim" 31 32 STATISTIC(CmpPromotionElemNum, "Number of shifts for CMP promotion 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 eliminateCmpPromotionSeq(void); 52 MachineInstr *getInsnDefZExtSubReg(unsigned Reg) const; 53 void updateInsnSeq(MachineBasicBlock &MBB, MachineInstr &MI, 54 unsigned Reg) const; 55 56 public: 57 58 // Main entry point for this pass. 59 bool runOnMachineFunction(MachineFunction &MF) override { 60 if (skipFunction(MF.getFunction())) 61 return false; 62 63 initialize(MF); 64 65 return eliminateCmpPromotionSeq(); 66 } 67 }; 68 69 // Initialize class variables. 70 void BPFMIPeephole::initialize(MachineFunction &MFParm) { 71 MF = &MFParm; 72 MRI = &MF->getRegInfo(); 73 TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo(); 74 DEBUG(dbgs() << "*** BPF MI peephole pass ***\n\n"); 75 } 76 77 MachineInstr *BPFMIPeephole::getInsnDefZExtSubReg(unsigned Reg) const { 78 MachineInstr *Insn = MRI->getVRegDef(Reg); 79 80 if (!Insn || 81 Insn->isPHI() || 82 Insn->getOpcode() != BPF::SRL_ri || 83 Insn->getOperand(2).getImm() != 32) 84 return nullptr; 85 86 Insn = MRI->getVRegDef(Insn->getOperand(1).getReg()); 87 if (!Insn || 88 Insn->isPHI() || 89 Insn->getOpcode() != BPF::SLL_ri || 90 Insn->getOperand(2).getImm() != 32) 91 return nullptr; 92 93 Insn = MRI->getVRegDef(Insn->getOperand(1).getReg()); 94 if (!Insn || 95 Insn->isPHI() || 96 Insn->getOpcode() != BPF::MOV_32_64) 97 return nullptr; 98 99 Insn = MRI->getVRegDef(Insn->getOperand(1).getReg()); 100 if (!Insn || Insn->isPHI()) 101 return nullptr; 102 103 if (Insn->getOpcode() == BPF::COPY) { 104 MachineOperand &opnd = Insn->getOperand(1); 105 106 if (!opnd.isReg()) 107 return nullptr; 108 109 unsigned Reg = opnd.getReg(); 110 if ((TargetRegisterInfo::isVirtualRegister(Reg) && 111 MRI->getRegClass(Reg) == &BPF::GPRRegClass) || 112 (TargetRegisterInfo::isPhysicalRegister(Reg) && 113 BPF::GPRRegClass.contains(Reg))) 114 return nullptr; 115 } 116 117 return Insn; 118 } 119 120 void 121 BPFMIPeephole::updateInsnSeq(MachineBasicBlock &MBB, MachineInstr &MI, 122 unsigned Reg) const { 123 MachineInstr *Mov, *Lshift, *Rshift; 124 unsigned SubReg; 125 DebugLoc DL; 126 127 Rshift = MRI->getVRegDef(Reg); 128 Lshift = MRI->getVRegDef(Rshift->getOperand(1).getReg()); 129 Mov = MRI->getVRegDef(Lshift->getOperand(1).getReg()); 130 SubReg = Mov->getOperand(1).getReg(); 131 DL = MI.getDebugLoc(); 132 BuildMI(MBB, Rshift, DL, TII->get(BPF::SUBREG_TO_REG), Reg) 133 .addImm(0).addReg(SubReg).addImm(BPF::sub_32); 134 Rshift->eraseFromParent(); 135 Lshift->eraseFromParent(); 136 Mov->eraseFromParent(); 137 138 CmpPromotionElemNum++; 139 } 140 141 bool BPFMIPeephole::eliminateCmpPromotionSeq(void) { 142 bool Eliminated = false; 143 MachineInstr *Mov; 144 unsigned Reg; 145 146 for (MachineBasicBlock &MBB : *MF) { 147 for (MachineInstr &MI : MBB) { 148 switch (MI.getOpcode()) { 149 default: 150 break; 151 case BPF::JUGT_rr: 152 case BPF::JUGE_rr: 153 case BPF::JULT_rr: 154 case BPF::JULE_rr: 155 case BPF::JEQ_rr: 156 case BPF::JNE_rr: 157 Reg = MI.getOperand(1).getReg(); 158 Mov = getInsnDefZExtSubReg(Reg); 159 if (!Mov) 160 break; 161 162 updateInsnSeq(MBB, MI, Reg); 163 Eliminated = true; 164 165 // Fallthrough 166 case BPF::JUGT_ri: 167 case BPF::JUGE_ri: 168 case BPF::JULT_ri: 169 case BPF::JULE_ri: 170 case BPF::JEQ_ri: 171 case BPF::JNE_ri: 172 Reg = MI.getOperand(0).getReg(); 173 Mov = getInsnDefZExtSubReg(Reg); 174 if (!Mov) 175 break; 176 177 updateInsnSeq(MBB, MI, Reg); 178 Eliminated = true; 179 break; 180 } 181 } 182 } 183 184 return Eliminated; 185 } 186 187 } // end default namespace 188 189 INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE, "BPF MI Peephole Optimization", 190 false, false) 191 192 char BPFMIPeephole::ID = 0; 193 FunctionPass* llvm::createBPFMIPeepholePass() { return new BPFMIPeephole(); } 194