diff options
Diffstat (limited to 'llvm/lib/Target/BPF/BPFMIPeephole.cpp')
-rw-r--r-- | llvm/lib/Target/BPF/BPFMIPeephole.cpp | 69 |
1 files changed, 59 insertions, 10 deletions
diff --git a/llvm/lib/Target/BPF/BPFMIPeephole.cpp b/llvm/lib/Target/BPF/BPFMIPeephole.cpp index 022267fbe3c2..df870314fffe 100644 --- a/llvm/lib/Target/BPF/BPFMIPeephole.cpp +++ b/llvm/lib/Target/BPF/BPFMIPeephole.cpp @@ -27,6 +27,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Support/Debug.h" +#include <set> using namespace llvm; @@ -56,6 +57,7 @@ private: bool isPhiFrom32Def(MachineInstr *MovMI); bool isMovFrom32Def(MachineInstr *MovMI); bool eliminateZExtSeq(void); + bool eliminateZExt(void); std::set<MachineInstr *> PhiInsns; @@ -68,7 +70,12 @@ public: initialize(MF); - return eliminateZExtSeq(); + // First try to eliminate (zext, lshift, rshift) and then + // try to eliminate zext. + bool ZExtSeqExist, ZExtExist; + ZExtSeqExist = eliminateZExtSeq(); + ZExtExist = eliminateZExt(); + return ZExtSeqExist || ZExtExist; } }; @@ -233,6 +240,51 @@ bool BPFMIPeephole::eliminateZExtSeq(void) { return Eliminated; } +bool BPFMIPeephole::eliminateZExt(void) { + MachineInstr* ToErase = nullptr; + bool Eliminated = false; + + for (MachineBasicBlock &MBB : *MF) { + for (MachineInstr &MI : MBB) { + // If the previous instruction was marked for elimination, remove it now. + if (ToErase) { + ToErase->eraseFromParent(); + ToErase = nullptr; + } + + if (MI.getOpcode() != BPF::MOV_32_64) + continue; + + // Eliminate MOV_32_64 if possible. + // MOV_32_64 rA, wB + // + // If wB has been zero extended, replace it with a SUBREG_TO_REG. + // This is to workaround BPF programs where pkt->{data, data_end} + // is encoded as u32, but actually the verifier populates them + // as 64bit pointer. The MOV_32_64 will zero out the top 32 bits. + LLVM_DEBUG(dbgs() << "Candidate MOV_32_64 instruction:"); + LLVM_DEBUG(MI.dump()); + + if (!isMovFrom32Def(&MI)) + continue; + + LLVM_DEBUG(dbgs() << "Removing the MOV_32_64 instruction\n"); + + Register dst = MI.getOperand(0).getReg(); + Register src = MI.getOperand(1).getReg(); + + // Build a SUBREG_TO_REG instruction. + BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::SUBREG_TO_REG), dst) + .addImm(0).addReg(src).addImm(BPF::sub_32); + + ToErase = &MI; + Eliminated = true; + } + } + + return Eliminated; +} + } // end default namespace INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE, @@ -300,19 +352,16 @@ bool BPFMIPreEmitPeephole::eliminateRedundantMov(void) { // // MOV rA, rA // - // This is particularly possible to happen when sub-register support - // enabled. The special type cast insn MOV_32_64 involves different - // register class on src (i32) and dst (i64), RA could generate useless - // instruction due to this. + // Note that we cannot remove + // MOV_32_64 rA, wA + // MOV_rr_32 wA, wA + // as these two instructions having side effects, zeroing out + // top 32 bits of rA. unsigned Opcode = MI.getOpcode(); - if (Opcode == BPF::MOV_32_64 || - Opcode == BPF::MOV_rr || Opcode == BPF::MOV_rr_32) { + if (Opcode == BPF::MOV_rr) { Register dst = MI.getOperand(0).getReg(); Register src = MI.getOperand(1).getReg(); - if (Opcode == BPF::MOV_32_64) - dst = TRI->getSubReg(dst, BPF::sub_32); - if (dst != src) continue; |