LLVM API Documentation
00001 //===-- SparcV9PeepholeOpts.cpp -------------------------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by the LLVM research group and is distributed under 00006 // the University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Support for performing several peephole opts in one or a few passes over the 00011 // machine code of a method. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "SparcV9Internals.h" 00016 #include "llvm/BasicBlock.h" 00017 #include "llvm/Pass.h" 00018 #include "llvm/CodeGen/MachineFunction.h" 00019 #include "llvm/CodeGen/MachineInstr.h" 00020 #include "llvm/Target/TargetInstrInfo.h" 00021 #include "llvm/Target/TargetMachine.h" 00022 #include "llvm/ADT/STLExtras.h" 00023 00024 namespace llvm { 00025 00026 //************************* Internal Functions *****************************/ 00027 00028 static inline void 00029 DeleteInstruction(MachineBasicBlock& mvec, 00030 MachineBasicBlock::iterator& BBI, 00031 const TargetMachine& target) { 00032 // Check if this instruction is in a delay slot of its predecessor. 00033 if (BBI != mvec.begin()) { 00034 const TargetInstrInfo& mii = *target.getInstrInfo(); 00035 MachineBasicBlock::iterator predMI = prior(BBI); 00036 if (unsigned ndelay = mii.getNumDelaySlots(predMI->getOpcode())) { 00037 // This instruction is in a delay slot of its predecessor, so 00038 // replace it with a nop. By replacing in place, we save having 00039 // to update the I-I maps. 00040 // 00041 assert(ndelay == 1 && "Not yet handling multiple-delay-slot targets"); 00042 BBI->replace(V9::NOP, 0); 00043 return; 00044 } 00045 } 00046 00047 // The instruction is not in a delay slot, so we can simply erase it. 00048 mvec.erase(BBI); 00049 BBI = mvec.end(); 00050 } 00051 00052 //******************* Individual Peephole Optimizations ********************/ 00053 00054 //---------------------------------------------------------------------------- 00055 // Function: IsUselessCopy 00056 // Decide whether a machine instruction is a redundant copy: 00057 // -- ADD with g0 and result and operand are identical, or 00058 // -- OR with g0 and result and operand are identical, or 00059 // -- FMOVS or FMOVD and result and operand are identical. 00060 // Other cases are possible but very rare that they would be useless copies, 00061 // so it's not worth analyzing them. 00062 //---------------------------------------------------------------------------- 00063 00064 static bool IsUselessCopy(const TargetMachine &target, const MachineInstr* MI) { 00065 if (MI->getOpcode() == V9::FMOVS || MI->getOpcode() == V9::FMOVD) { 00066 return (// both operands are allocated to the same register 00067 MI->getOperand(0).getReg() == MI->getOperand(1).getReg()); 00068 } else if (MI->getOpcode() == V9::ADDr || MI->getOpcode() == V9::ORr || 00069 MI->getOpcode() == V9::ADDi || MI->getOpcode() == V9::ORi) { 00070 unsigned srcWithDestReg; 00071 00072 for (srcWithDestReg = 0; srcWithDestReg < 2; ++srcWithDestReg) 00073 if (MI->getOperand(srcWithDestReg).hasAllocatedReg() && 00074 MI->getOperand(srcWithDestReg).getReg() 00075 == MI->getOperand(2).getReg()) 00076 break; 00077 00078 if (srcWithDestReg == 2) 00079 return false; 00080 else { 00081 // else source and dest are allocated to the same register 00082 unsigned otherOp = 1 - srcWithDestReg; 00083 return (// either operand otherOp is register %g0 00084 (MI->getOperand(otherOp).hasAllocatedReg() && 00085 MI->getOperand(otherOp).getReg() == 00086 target.getRegInfo()->getZeroRegNum()) || 00087 00088 // or operand otherOp == 0 00089 (MI->getOperand(otherOp).getType() 00090 == MachineOperand::MO_SignExtendedImmed && 00091 MI->getOperand(otherOp).getImmedValue() == 0)); 00092 } 00093 } 00094 else 00095 return false; 00096 } 00097 00098 inline bool 00099 RemoveUselessCopies(MachineBasicBlock& mvec, 00100 MachineBasicBlock::iterator& BBI, 00101 const TargetMachine& target) { 00102 if (IsUselessCopy(target, BBI)) { 00103 DeleteInstruction(mvec, BBI, target); 00104 return true; 00105 } 00106 return false; 00107 } 00108 00109 00110 //************************ Class Implementations **************************/ 00111 00112 class PeepholeOpts: public BasicBlockPass { 00113 const TargetMachine ⌖ 00114 bool visit(MachineBasicBlock& mvec, 00115 MachineBasicBlock::iterator BBI) const; 00116 public: 00117 PeepholeOpts(const TargetMachine &TM): target(TM) { } 00118 bool runOnBasicBlock(BasicBlock &BB); // apply this pass to each BB 00119 virtual const char *getPassName() const { return "Peephole Optimization"; } 00120 00121 // getAnalysisUsage - this pass preserves the CFG 00122 void getAnalysisUsage(AnalysisUsage &AU) const { 00123 AU.setPreservesCFG(); 00124 } 00125 }; 00126 00127 // Apply a list of peephole optimizations to this machine instruction 00128 // within its local context. They are allowed to delete MI or any 00129 // instruction before MI, but not 00130 // 00131 bool PeepholeOpts::visit(MachineBasicBlock& mvec, 00132 MachineBasicBlock::iterator BBI) const { 00133 // Remove redundant copy instructions 00134 return RemoveUselessCopies(mvec, BBI, target); 00135 } 00136 00137 00138 bool PeepholeOpts::runOnBasicBlock(BasicBlock &BB) { 00139 // Get the machine instructions for this BB 00140 // FIXME: MachineBasicBlock::get() is deprecated, hence inlining the function 00141 const Function *F = BB.getParent(); 00142 MachineFunction &MF = MachineFunction::get(F); 00143 MachineBasicBlock *MBB = NULL; 00144 for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) 00145 if (I->getBasicBlock() == &BB) 00146 MBB = I; 00147 00148 assert(MBB && "MachineBasicBlock object not found for specified block!"); 00149 MachineBasicBlock &mvec = *MBB; 00150 00151 for (MachineBasicBlock::iterator I = mvec.begin(), E = mvec.end(); I != E; ) 00152 visit(mvec, I++); 00153 00154 return true; 00155 } 00156 00157 /// createPeepholeOptsPass - Public entry point for peephole optimization 00158 /// 00159 FunctionPass* createPeepholeOptsPass(const TargetMachine &TM) { 00160 return new PeepholeOpts(TM); 00161 } 00162 00163 } // End llvm namespace