bpf: New optimization pass for eliminating unnecessary i32 promotions
authorYonghong Song <yhs@fb.com>
Fri, 23 Feb 2018 23:49:32 +0000 (23:49 +0000)
committerYonghong Song <yhs@fb.com>
Fri, 23 Feb 2018 23:49:32 +0000 (23:49 +0000)
This pass performs peephole optimizations to cleanup ugly code sequences at
MachineInstruction layer.

Currently, the only optimization in this pass is to eliminate type
promotion
sequences for zero extending 32-bit subregisters to 64-bit registers.

If the compiler could prove the zero extended source come from 32-bit
subregistere then it is safe to erase those promotion sequece, because the
upper half of the underlying 64-bit registers were zeroed implicitly
already.

Signed-off-by: Jiong Wang <jiong.wang@netronome.com>
Reviewed-by: Yonghong Song <yhs@fb.com>
llvm-svn: 325991

llvm/lib/Target/BPF/BPF.h
llvm/lib/Target/BPF/BPFMIPeephole.cpp [new file with mode: 0644]
llvm/lib/Target/BPF/BPFTargetMachine.cpp
llvm/lib/Target/BPF/CMakeLists.txt

index 4a0cb20..8b94ba1 100644 (file)
@@ -17,6 +17,9 @@ namespace llvm {
 class BPFTargetMachine;
 
 FunctionPass *createBPFISelDag(BPFTargetMachine &TM);
+FunctionPass *createBPFMIPeepholePass();
+
+void initializeBPFMIPeepholePass(PassRegistry&);
 }
 
 #endif
diff --git a/llvm/lib/Target/BPF/BPFMIPeephole.cpp b/llvm/lib/Target/BPF/BPFMIPeephole.cpp
new file mode 100644 (file)
index 0000000..80f4437
--- /dev/null
@@ -0,0 +1,175 @@
+//===-------------- BPFMIPeephole.cpp - MI Peephole Cleanups  -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass performs peephole optimizations to cleanup ugly code sequences at
+// MachineInstruction layer.
+//
+// Currently, the only optimization in this pass is to eliminate type promotion
+// sequences, those zero extend 32-bit subregisters to 64-bit registers, if the
+// compiler could prove the subregisters is defined by 32-bit operations in
+// which case the upper half of the underlying 64-bit registers were zeroed
+// implicitly.
+//
+//===----------------------------------------------------------------------===//
+
+#include "BPF.h"
+#include "BPFInstrInfo.h"
+#include "BPFTargetMachine.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "bpf-mi-promotion-elim"
+
+STATISTIC(CmpPromotionElemNum, "Number of shifts for CMP promotion eliminated");
+
+namespace {
+
+struct BPFMIPeephole : public MachineFunctionPass {
+
+  static char ID;
+  const BPFInstrInfo *TII;
+  MachineFunction *MF;
+  MachineRegisterInfo *MRI;
+
+  BPFMIPeephole() : MachineFunctionPass(ID) {
+    initializeBPFMIPeepholePass(*PassRegistry::getPassRegistry());
+  }
+
+private:
+  // Initialize class variables.
+  void initialize(MachineFunction &MFParm);
+
+  bool eliminateCmpPromotionSeq(void);
+  MachineInstr *getInsnDefZExtSubReg(unsigned Reg) const;
+  void updateInsnSeq(MachineBasicBlock &MBB, MachineInstr &MI,
+                     unsigned Reg) const;
+
+public:
+
+  // Main entry point for this pass.
+  bool runOnMachineFunction(MachineFunction &MF) override {
+    if (skipFunction(MF.getFunction()))
+      return false;
+
+    initialize(MF);
+
+    return eliminateCmpPromotionSeq();
+  }
+};
+
+// Initialize class variables.
+void BPFMIPeephole::initialize(MachineFunction &MFParm) {
+  MF = &MFParm;
+  MRI = &MF->getRegInfo();
+  TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
+  DEBUG(dbgs() << "*** BPF MI peephole pass ***\n\n");
+}
+
+MachineInstr *BPFMIPeephole::getInsnDefZExtSubReg(unsigned Reg) const {
+  MachineInstr *Insn = MRI->getVRegDef(Reg);
+
+  if (!Insn ||
+      Insn->isPHI() ||
+      Insn->getOpcode() != BPF::SRL_ri ||
+      Insn->getOperand(2).getImm() != 32)
+    return nullptr;
+
+  Insn = MRI->getVRegDef(Insn->getOperand(1).getReg());
+  if (!Insn ||
+      Insn->isPHI() ||
+      Insn->getOpcode() != BPF::SLL_ri ||
+      Insn->getOperand(2).getImm() != 32)
+    return nullptr;
+
+  Insn = MRI->getVRegDef(Insn->getOperand(1).getReg());
+  if (!Insn ||
+      Insn->isPHI() ||
+      Insn->getOpcode() != BPF::MOV_32_64)
+    return nullptr;
+
+  return Insn;
+}
+
+void
+BPFMIPeephole::updateInsnSeq(MachineBasicBlock &MBB, MachineInstr &MI,
+                             unsigned Reg) const {
+  MachineInstr *Mov, *Lshift, *Rshift;
+  unsigned SubReg;
+  DebugLoc DL;
+
+  Rshift = MRI->getVRegDef(Reg);
+  Lshift = MRI->getVRegDef(Rshift->getOperand(1).getReg());
+  Mov = MRI->getVRegDef(Lshift->getOperand(1).getReg());
+  SubReg = Mov->getOperand(1).getReg();
+  DL = MI.getDebugLoc();
+  BuildMI(MBB, Rshift, DL, TII->get(BPF::SUBREG_TO_REG), Reg)
+    .addImm(0).addReg(SubReg).addImm(BPF::sub_32);
+  Rshift->eraseFromParent();
+  Lshift->eraseFromParent();
+  Mov->eraseFromParent();
+
+  CmpPromotionElemNum++;
+}
+
+bool BPFMIPeephole::eliminateCmpPromotionSeq(void) {
+  bool Eliminated = false;
+  MachineInstr *Mov;
+  unsigned Reg;
+
+  for (MachineBasicBlock &MBB : *MF) {
+    for (MachineInstr &MI : MBB) {
+      switch (MI.getOpcode()) {
+      default:
+        break;
+      case BPF::JUGT_rr:
+      case BPF::JUGE_rr:
+      case BPF::JULT_rr:
+      case BPF::JULE_rr:
+      case BPF::JEQ_rr:
+      case BPF::JNE_rr:
+        Reg = MI.getOperand(1).getReg();
+        Mov = getInsnDefZExtSubReg(Reg);
+        if (!Mov)
+          break;
+
+       updateInsnSeq(MBB, MI, Reg);
+       Eliminated = true;
+
+        // Fallthrough
+      case BPF::JUGT_ri:
+      case BPF::JUGE_ri:
+      case BPF::JULT_ri:
+      case BPF::JULE_ri:
+      case BPF::JEQ_ri:
+      case BPF::JNE_ri:
+        Reg = MI.getOperand(0).getReg();
+        Mov = getInsnDefZExtSubReg(Reg);
+        if (!Mov)
+          break;
+
+       updateInsnSeq(MBB, MI, Reg);
+       Eliminated = true;
+        break;
+      }
+    }
+  }
+
+  return Eliminated;
+}
+
+} // end default namespace
+
+INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE, "BPF MI Peephole Optimization",
+                false, false)
+
+char BPFMIPeephole::ID = 0;
+FunctionPass* llvm::createBPFMIPeepholePass() { return new BPFMIPeephole(); }
index 60672fa..0114d18 100644 (file)
 #include "llvm/Target/TargetOptions.h"
 using namespace llvm;
 
+static cl::
+opt<bool> DisableMIPeephole("disable-bpf-peephole", cl::Hidden,
+                            cl::desc("Disable machine peepholes for BPF"));
+
 extern "C" void LLVMInitializeBPFTarget() {
   // Register the target.
   RegisterTargetMachine<BPFTargetMachine> X(getTheBPFleTarget());
   RegisterTargetMachine<BPFTargetMachine> Y(getTheBPFbeTarget());
   RegisterTargetMachine<BPFTargetMachine> Z(getTheBPFTarget());
+
+  PassRegistry &PR = *PassRegistry::getPassRegistry();
+  initializeBPFMIPeepholePass(PR);
 }
 
 // DataLayout: little or big endian
@@ -74,6 +81,7 @@ public:
   }
 
   bool addInstSelector() override;
+  void addMachineSSAOptimization() override;
 };
 }
 
@@ -88,3 +96,13 @@ bool BPFPassConfig::addInstSelector() {
 
   return false;
 }
+
+void BPFPassConfig::addMachineSSAOptimization() {
+  // The default implementation must be called first as we want eBPF
+  // Peephole ran at last.
+  TargetPassConfig::addMachineSSAOptimization();
+
+  const BPFSubtarget *Subtarget = getBPFTargetMachine().getSubtargetImpl();
+  if (Subtarget->getHasAlu32() && !DisableMIPeephole)
+    addPass(createBPFMIPeepholePass());
+}
index 1e4b685..c3d2e48 100644 (file)
@@ -21,6 +21,7 @@ add_llvm_target(BPFCodeGen
   BPFRegisterInfo.cpp
   BPFSubtarget.cpp
   BPFTargetMachine.cpp
+  BPFMIPeephole.cpp
   )
 
 add_subdirectory(AsmParser)