This class is no longer an annotation
[oota-llvm.git] / lib / Target / SparcV9 / SparcV9PeepholeOpts.cpp
index 3912f4e7629c5e75e059f1107276aa36e58ce3a9..d80a543b476c9495755d6547619f4f3d6d8ccc99 100644 (file)
@@ -1,37 +1,45 @@
-//===-- PeepholeOpts.cpp --------------------------------------------------===//
+//===-- SparcV9PeepholeOpts.cpp -------------------------------------------===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
 // 
 // Support for performing several peephole opts in one or a few passes over the
 // machine code of a method.
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/CodeGen/PeepholeOpts.h"
+#include "SparcV9Internals.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Pass.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetOptInfo.h"
-#include "llvm/BasicBlock.h"
-#include "llvm/Pass.h"
+#include "llvm/Target/TargetMachine.h"
+#include "Support/STLExtras.h"
+
+namespace llvm {
 
 //************************* Internal Functions *****************************/
 
-inline void
+static inline void
 DeleteInstruction(MachineBasicBlock& mvec,
                   MachineBasicBlock::iterator& BBI,
-                  const TargetMachine& target)
-{
+                  const TargetMachine& target) {
   // Check if this instruction is in a delay slot of its predecessor.
   if (BBI != mvec.begin()) {
-      const TargetInstrInfo& mii = target.getInstrInfo();
-      MachineInstr* predMI = *(BBI-1);
-      if (unsigned ndelay = mii.getNumDelaySlots(predMI->getOpCode())) {
+      const TargetInstrInfo& mii = *target.getInstrInfo();
+      MachineBasicBlock::iterator predMI = prior(BBI);
+      if (unsigned ndelay = mii.getNumDelaySlots(predMI->getOpcode())) {
         // This instruction is in a delay slot of its predecessor, so
         // replace it with a nop. By replacing in place, we save having
         // to update the I-I maps.
         // 
         assert(ndelay == 1 && "Not yet handling multiple-delay-slot targets");
-        (*BBI)->replace(mii.getNOPOpCode(), 0);
+        BBI->replace(mii.getNOPOpCode(), 0);
         return;
       }
   }
@@ -43,13 +51,55 @@ DeleteInstruction(MachineBasicBlock& mvec,
 
 //******************* Individual Peephole Optimizations ********************/
 
+//----------------------------------------------------------------------------
+// Function: IsUselessCopy
+// Decide whether a machine instruction is a redundant copy:
+// -- ADD    with g0 and result and operand are identical, or
+// -- OR     with g0 and result and operand are identical, or
+// -- FMOVS or FMOVD and result and operand are identical.
+// Other cases are possible but very rare that they would be useless copies,
+// so it's not worth analyzing them.
+//----------------------------------------------------------------------------
+
+static bool IsUselessCopy(const TargetMachine &target, const MachineInstr* MI) {
+  if (MI->getOpcode() == V9::FMOVS || MI->getOpcode() == V9::FMOVD) {
+    return (// both operands are allocated to the same register
+            MI->getOperand(0).getReg() ==  MI->getOperand(1).getReg());
+  } else if (MI->getOpcode() == V9::ADDr || MI->getOpcode() == V9::ORr ||
+             MI->getOpcode() == V9::ADDi || MI->getOpcode() == V9::ORi) {
+    unsigned srcWithDestReg;
+    
+    for (srcWithDestReg = 0; srcWithDestReg < 2; ++srcWithDestReg)
+      if (MI->getOperand(srcWithDestReg).hasAllocatedReg() &&
+          MI->getOperand(srcWithDestReg).getReg()
+          == MI->getOperand(2).getReg())
+        break;
+    
+    if (srcWithDestReg == 2)
+      return false;
+    else {
+      // else source and dest are allocated to the same register
+      unsigned otherOp = 1 - srcWithDestReg;
+      return (// either operand otherOp is register %g0
+              (MI->getOperand(otherOp).hasAllocatedReg() &&
+               MI->getOperand(otherOp).getReg() ==
+               target.getRegInfo()->getZeroRegNum()) ||
+              
+              // or operand otherOp == 0
+              (MI->getOperand(otherOp).getType()
+               == MachineOperand::MO_SignExtendedImmed &&
+               MI->getOperand(otherOp).getImmedValue() == 0));
+    }
+  }
+  else
+    return false;
+}
 
 inline bool
 RemoveUselessCopies(MachineBasicBlock& mvec,
                     MachineBasicBlock::iterator& BBI,
-                    const TargetMachine& target)
-{
-  if (target.getOptInfo().IsUselessCopy(*BBI)) {
+                    const TargetMachine& target) {
+  if (IsUselessCopy(target, BBI)) {
     DeleteInstruction(mvec, BBI, target);
     return true;
   }
@@ -64,66 +114,50 @@ class PeepholeOpts: public BasicBlockPass {
   bool visit(MachineBasicBlock& mvec,
              MachineBasicBlock::iterator BBI) const;
 public:
-  PeepholeOpts(const TargetMachine &T): target(T) { }
+  PeepholeOpts(const TargetMachine &TM): target(TM) { }
   bool runOnBasicBlock(BasicBlock &BB); // apply this pass to each BB
+  virtual const char *getPassName() const { return "Peephole Optimization"; }
+
+  // getAnalysisUsage - this pass preserves the CFG
+  void getAnalysisUsage(AnalysisUsage &AU) const {
+    AU.setPreservesCFG();
+  }
 };
 
-/* Apply a list of peephole optimizations to this machine instruction
- * within its local context.  They are allowed to delete MI or any
- * instruction before MI, but not 
- */
-bool
-PeepholeOpts::visit(MachineBasicBlock& mvec,
-                    MachineBasicBlock::iterator BBI) const
-{
-  bool changed = false;
-
-  /* Remove redundant copy instructions */
-  changed |= RemoveUselessCopies(mvec, BBI, target);
-  if (BBI == mvec.end())                // nothing more to do!
-    return changed;
-
-  return changed;
+// Apply a list of peephole optimizations to this machine instruction
+// within its local context.  They are allowed to delete MI or any
+// instruction before MI, but not 
+//
+bool PeepholeOpts::visit(MachineBasicBlock& mvec,
+                         MachineBasicBlock::iterator BBI) const {
+  // Remove redundant copy instructions
+  return RemoveUselessCopies(mvec, BBI, target);
 }
 
 
-bool
-PeepholeOpts::runOnBasicBlock(BasicBlock &BB)
-{
+bool PeepholeOpts::runOnBasicBlock(BasicBlock &BB) {
   // Get the machine instructions for this BB
   // FIXME: MachineBasicBlock::get() is deprecated, hence inlining the function
   const Function *F = BB.getParent();
   MachineFunction &MF = MachineFunction::get(F);
   MachineBasicBlock *MBB = NULL;
-  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
+  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
     if (I->getBasicBlock() == &BB)
       MBB = I;
-  }
+
   assert(MBB && "MachineBasicBlock object not found for specified block!");
   MachineBasicBlock &mvec = *MBB;
 
-  // Iterate over all machine instructions in the BB
-  // Use a reverse iterator to allow deletion of MI or any instruction after it.
-  // Insertions or deletions *before* MI are not safe.
-  // 
-  for (MachineBasicBlock::reverse_iterator RI=mvec.rbegin(),
-         RE=mvec.rend(); RI != RE; )
-  {
-    MachineBasicBlock::iterator BBI = RI.base()-1; // save before incr
-    ++RI;             // pre-increment to delete MI or after it
-    visit(mvec, BBI);
-  }
+  for (MachineBasicBlock::iterator I = mvec.begin(), E = mvec.end(); I != E; )
+    visit(mvec, I++);
 
   return true;
 }
 
-
-//===----------------------------------------------------------------------===//
-// createPeepholeOptsPass - Public entrypoint for peephole optimization
-// and this file as a whole...
-//
-FunctionPass*
-createPeepholeOptsPass(TargetMachine &T)
-{
-  return new PeepholeOpts(T);
+/// createPeepholeOptsPass - Public entry point for peephole optimization
+///
+FunctionPass* createPeepholeOptsPass(const TargetMachine &TM) {
+  return new PeepholeOpts(TM);
 }
+
+} // End llvm namespace