HexagonPeephole.cpp revision 249423
1234285Sdim//===-- HexagonPeephole.cpp - Hexagon Peephole Optimiztions ---------------===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim// This peephole pass optimizes in the following cases. 9234285Sdim// 1. Optimizes redundant sign extends for the following case 10234285Sdim// Transform the following pattern 11234285Sdim// %vreg170<def> = SXTW %vreg166 12234285Sdim// ... 13234285Sdim// %vreg176<def> = COPY %vreg170:subreg_loreg 14234285Sdim// 15234285Sdim// Into 16234285Sdim// %vreg176<def> = COPY vreg166 17234285Sdim// 18234285Sdim// 2. Optimizes redundant negation of predicates. 19234285Sdim// %vreg15<def> = CMPGTrr %vreg6, %vreg2 20234285Sdim// ... 21234285Sdim// %vreg16<def> = NOT_p %vreg15<kill> 22234285Sdim// ... 23234285Sdim// JMP_c %vreg16<kill>, <BB#1>, %PC<imp-def,dead> 24234285Sdim// 25234285Sdim// Into 26234285Sdim// %vreg15<def> = CMPGTrr %vreg6, %vreg2; 27234285Sdim// ... 28234285Sdim// JMP_cNot %vreg15<kill>, <BB#1>, %PC<imp-def,dead>; 29234285Sdim// 30234285Sdim// Note: The peephole pass makes the instrucstions like 31234285Sdim// %vreg170<def> = SXTW %vreg166 or %vreg16<def> = NOT_p %vreg15<kill> 32234285Sdim// redundant and relies on some form of dead removal instrucions, like 33234285Sdim// DCE or DIE to actually eliminate them. 34234285Sdim 35234285Sdim 36234285Sdim//===----------------------------------------------------------------------===// 37234285Sdim 38234285Sdim#define DEBUG_TYPE "hexagon-peephole" 39234285Sdim#include "Hexagon.h" 40234285Sdim#include "HexagonTargetMachine.h" 41234285Sdim#include "llvm/ADT/DenseMap.h" 42234285Sdim#include "llvm/ADT/Statistic.h" 43234285Sdim#include "llvm/CodeGen/MachineFunction.h" 44234285Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 45234285Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 46234285Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 47249423Sdim#include "llvm/CodeGen/Passes.h" 48249423Sdim#include "llvm/IR/Constants.h" 49249423Sdim#include "llvm/PassSupport.h" 50234285Sdim#include "llvm/Support/CommandLine.h" 51234285Sdim#include "llvm/Support/Debug.h" 52234285Sdim#include "llvm/Support/raw_ostream.h" 53249423Sdim#include "llvm/Target/TargetInstrInfo.h" 54234285Sdim#include "llvm/Target/TargetMachine.h" 55234285Sdim#include "llvm/Target/TargetRegisterInfo.h" 56234285Sdim#include <algorithm> 57234285Sdim 58234285Sdimusing namespace llvm; 59234285Sdim 60234285Sdimstatic cl::opt<bool> DisableHexagonPeephole("disable-hexagon-peephole", 61234285Sdim cl::Hidden, cl::ZeroOrMore, cl::init(false), 62234285Sdim cl::desc("Disable Peephole Optimization")); 63234285Sdim 64234285Sdimstatic cl::opt<int> 65234285SdimDbgPNPCount("pnp-count", cl::init(-1), cl::Hidden, 66234285Sdim cl::desc("Maximum number of P=NOT(P) to be optimized")); 67234285Sdim 68234285Sdimstatic cl::opt<bool> DisablePNotP("disable-hexagon-pnotp", 69234285Sdim cl::Hidden, cl::ZeroOrMore, cl::init(false), 70234285Sdim cl::desc("Disable Optimization of PNotP")); 71234285Sdim 72234285Sdimstatic cl::opt<bool> DisableOptSZExt("disable-hexagon-optszext", 73234285Sdim cl::Hidden, cl::ZeroOrMore, cl::init(false), 74234285Sdim cl::desc("Disable Optimization of Sign/Zero Extends")); 75234285Sdim 76234285Sdimnamespace { 77234285Sdim struct HexagonPeephole : public MachineFunctionPass { 78234285Sdim const HexagonInstrInfo *QII; 79234285Sdim const HexagonRegisterInfo *QRI; 80234285Sdim const MachineRegisterInfo *MRI; 81234285Sdim 82234285Sdim public: 83234285Sdim static char ID; 84234285Sdim HexagonPeephole() : MachineFunctionPass(ID) { } 85234285Sdim 86234285Sdim bool runOnMachineFunction(MachineFunction &MF); 87234285Sdim 88234285Sdim const char *getPassName() const { 89234285Sdim return "Hexagon optimize redundant zero and size extends"; 90234285Sdim } 91234285Sdim 92234285Sdim void getAnalysisUsage(AnalysisUsage &AU) const { 93234285Sdim MachineFunctionPass::getAnalysisUsage(AU); 94234285Sdim } 95234285Sdim 96234285Sdim private: 97234285Sdim void ChangeOpInto(MachineOperand &Dst, MachineOperand &Src); 98234285Sdim }; 99234285Sdim} 100234285Sdim 101234285Sdimchar HexagonPeephole::ID = 0; 102234285Sdim 103234285Sdimbool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { 104234285Sdim 105234285Sdim QII = static_cast<const HexagonInstrInfo *>(MF.getTarget(). 106234285Sdim getInstrInfo()); 107234285Sdim QRI = static_cast<const HexagonRegisterInfo *>(MF.getTarget(). 108234285Sdim getRegisterInfo()); 109234285Sdim MRI = &MF.getRegInfo(); 110234285Sdim 111234285Sdim DenseMap<unsigned, unsigned> PeepholeMap; 112243830Sdim DenseMap<unsigned, std::pair<unsigned, unsigned> > PeepholeDoubleRegsMap; 113234285Sdim 114234285Sdim if (DisableHexagonPeephole) return false; 115234285Sdim 116234285Sdim // Loop over all of the basic blocks. 117234285Sdim for (MachineFunction::iterator MBBb = MF.begin(), MBBe = MF.end(); 118234285Sdim MBBb != MBBe; ++MBBb) { 119234285Sdim MachineBasicBlock* MBB = MBBb; 120234285Sdim PeepholeMap.clear(); 121243830Sdim PeepholeDoubleRegsMap.clear(); 122234285Sdim 123234285Sdim // Traverse the basic block. 124234285Sdim for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end(); 125234285Sdim ++MII) { 126234285Sdim MachineInstr *MI = MII; 127234285Sdim // Look for sign extends: 128234285Sdim // %vreg170<def> = SXTW %vreg166 129234285Sdim if (!DisableOptSZExt && MI->getOpcode() == Hexagon::SXTW) { 130234285Sdim assert (MI->getNumOperands() == 2); 131234285Sdim MachineOperand &Dst = MI->getOperand(0); 132234285Sdim MachineOperand &Src = MI->getOperand(1); 133234285Sdim unsigned DstReg = Dst.getReg(); 134234285Sdim unsigned SrcReg = Src.getReg(); 135234285Sdim // Just handle virtual registers. 136234285Sdim if (TargetRegisterInfo::isVirtualRegister(DstReg) && 137234285Sdim TargetRegisterInfo::isVirtualRegister(SrcReg)) { 138234285Sdim // Map the following: 139234285Sdim // %vreg170<def> = SXTW %vreg166 140234285Sdim // PeepholeMap[170] = vreg166 141234285Sdim PeepholeMap[DstReg] = SrcReg; 142234285Sdim } 143234285Sdim } 144234285Sdim 145243830Sdim // Look for this sequence below 146243830Sdim // %vregDoubleReg1 = LSRd_ri %vregDoubleReg0, 32 147243830Sdim // %vregIntReg = COPY %vregDoubleReg1:subreg_loreg. 148243830Sdim // and convert into 149243830Sdim // %vregIntReg = COPY %vregDoubleReg0:subreg_hireg. 150243830Sdim if (MI->getOpcode() == Hexagon::LSRd_ri) { 151243830Sdim assert(MI->getNumOperands() == 3); 152243830Sdim MachineOperand &Dst = MI->getOperand(0); 153243830Sdim MachineOperand &Src1 = MI->getOperand(1); 154243830Sdim MachineOperand &Src2 = MI->getOperand(2); 155243830Sdim if (Src2.getImm() != 32) 156243830Sdim continue; 157243830Sdim unsigned DstReg = Dst.getReg(); 158243830Sdim unsigned SrcReg = Src1.getReg(); 159243830Sdim PeepholeDoubleRegsMap[DstReg] = 160243830Sdim std::make_pair(*&SrcReg, 1/*Hexagon::subreg_hireg*/); 161243830Sdim } 162243830Sdim 163234285Sdim // Look for P=NOT(P). 164234285Sdim if (!DisablePNotP && 165234285Sdim (MI->getOpcode() == Hexagon::NOT_p)) { 166234285Sdim assert (MI->getNumOperands() == 2); 167234285Sdim MachineOperand &Dst = MI->getOperand(0); 168234285Sdim MachineOperand &Src = MI->getOperand(1); 169234285Sdim unsigned DstReg = Dst.getReg(); 170234285Sdim unsigned SrcReg = Src.getReg(); 171234285Sdim // Just handle virtual registers. 172234285Sdim if (TargetRegisterInfo::isVirtualRegister(DstReg) && 173234285Sdim TargetRegisterInfo::isVirtualRegister(SrcReg)) { 174234285Sdim // Map the following: 175234285Sdim // %vreg170<def> = NOT_xx %vreg166 176234285Sdim // PeepholeMap[170] = vreg166 177234285Sdim PeepholeMap[DstReg] = SrcReg; 178234285Sdim } 179234285Sdim } 180234285Sdim 181234285Sdim // Look for copy: 182234285Sdim // %vreg176<def> = COPY %vreg170:subreg_loreg 183234285Sdim if (!DisableOptSZExt && MI->isCopy()) { 184234285Sdim assert (MI->getNumOperands() == 2); 185234285Sdim MachineOperand &Dst = MI->getOperand(0); 186234285Sdim MachineOperand &Src = MI->getOperand(1); 187234285Sdim 188234285Sdim // Make sure we are copying the lower 32 bits. 189234285Sdim if (Src.getSubReg() != Hexagon::subreg_loreg) 190234285Sdim continue; 191234285Sdim 192234285Sdim unsigned DstReg = Dst.getReg(); 193234285Sdim unsigned SrcReg = Src.getReg(); 194234285Sdim if (TargetRegisterInfo::isVirtualRegister(DstReg) && 195234285Sdim TargetRegisterInfo::isVirtualRegister(SrcReg)) { 196234285Sdim // Try to find in the map. 197234285Sdim if (unsigned PeepholeSrc = PeepholeMap.lookup(SrcReg)) { 198234285Sdim // Change the 1st operand. 199234285Sdim MI->RemoveOperand(1); 200234285Sdim MI->addOperand(MachineOperand::CreateReg(PeepholeSrc, false)); 201243830Sdim } else { 202243830Sdim DenseMap<unsigned, std::pair<unsigned, unsigned> >::iterator DI = 203243830Sdim PeepholeDoubleRegsMap.find(SrcReg); 204243830Sdim if (DI != PeepholeDoubleRegsMap.end()) { 205243830Sdim std::pair<unsigned,unsigned> PeepholeSrc = DI->second; 206243830Sdim MI->RemoveOperand(1); 207243830Sdim MI->addOperand(MachineOperand::CreateReg(PeepholeSrc.first, 208243830Sdim false /*isDef*/, 209243830Sdim false /*isImp*/, 210243830Sdim false /*isKill*/, 211243830Sdim false /*isDead*/, 212243830Sdim false /*isUndef*/, 213243830Sdim false /*isEarlyClobber*/, 214243830Sdim PeepholeSrc.second)); 215243830Sdim } 216234285Sdim } 217234285Sdim } 218234285Sdim } 219234285Sdim 220234285Sdim // Look for Predicated instructions. 221234285Sdim if (!DisablePNotP) { 222234285Sdim bool Done = false; 223234285Sdim if (QII->isPredicated(MI)) { 224234285Sdim MachineOperand &Op0 = MI->getOperand(0); 225234285Sdim unsigned Reg0 = Op0.getReg(); 226234285Sdim const TargetRegisterClass *RC0 = MRI->getRegClass(Reg0); 227234285Sdim if (RC0->getID() == Hexagon::PredRegsRegClassID) { 228234285Sdim // Handle instructions that have a prediate register in op0 229234285Sdim // (most cases of predicable instructions). 230234285Sdim if (TargetRegisterInfo::isVirtualRegister(Reg0)) { 231234285Sdim // Try to find in the map. 232234285Sdim if (unsigned PeepholeSrc = PeepholeMap.lookup(Reg0)) { 233234285Sdim // Change the 1st operand and, flip the opcode. 234234285Sdim MI->getOperand(0).setReg(PeepholeSrc); 235234285Sdim int NewOp = QII->getInvertedPredicatedOpcode(MI->getOpcode()); 236234285Sdim MI->setDesc(QII->get(NewOp)); 237234285Sdim Done = true; 238234285Sdim } 239234285Sdim } 240234285Sdim } 241234285Sdim } 242234285Sdim 243234285Sdim if (!Done) { 244234285Sdim // Handle special instructions. 245234285Sdim unsigned Op = MI->getOpcode(); 246234285Sdim unsigned NewOp = 0; 247234285Sdim unsigned PR = 1, S1 = 2, S2 = 3; // Operand indices. 248234285Sdim 249234285Sdim switch (Op) { 250234285Sdim case Hexagon::TFR_condset_rr: 251234285Sdim case Hexagon::TFR_condset_ii: 252234285Sdim case Hexagon::MUX_ii: 253234285Sdim case Hexagon::MUX_rr: 254234285Sdim NewOp = Op; 255234285Sdim break; 256234285Sdim case Hexagon::TFR_condset_ri: 257234285Sdim NewOp = Hexagon::TFR_condset_ir; 258234285Sdim break; 259234285Sdim case Hexagon::TFR_condset_ir: 260234285Sdim NewOp = Hexagon::TFR_condset_ri; 261234285Sdim break; 262234285Sdim case Hexagon::MUX_ri: 263234285Sdim NewOp = Hexagon::MUX_ir; 264234285Sdim break; 265234285Sdim case Hexagon::MUX_ir: 266234285Sdim NewOp = Hexagon::MUX_ri; 267234285Sdim break; 268234285Sdim } 269234285Sdim if (NewOp) { 270234285Sdim unsigned PSrc = MI->getOperand(PR).getReg(); 271234285Sdim if (unsigned POrig = PeepholeMap.lookup(PSrc)) { 272234285Sdim MI->getOperand(PR).setReg(POrig); 273234285Sdim MI->setDesc(QII->get(NewOp)); 274234285Sdim // Swap operands S1 and S2. 275234285Sdim MachineOperand Op1 = MI->getOperand(S1); 276234285Sdim MachineOperand Op2 = MI->getOperand(S2); 277234285Sdim ChangeOpInto(MI->getOperand(S1), Op2); 278234285Sdim ChangeOpInto(MI->getOperand(S2), Op1); 279234285Sdim } 280234285Sdim } // if (NewOp) 281234285Sdim } // if (!Done) 282234285Sdim 283234285Sdim } // if (!DisablePNotP) 284234285Sdim 285234285Sdim } // Instruction 286234285Sdim } // Basic Block 287234285Sdim return true; 288234285Sdim} 289234285Sdim 290234285Sdimvoid HexagonPeephole::ChangeOpInto(MachineOperand &Dst, MachineOperand &Src) { 291234285Sdim assert (&Dst != &Src && "Cannot duplicate into itself"); 292234285Sdim switch (Dst.getType()) { 293234285Sdim case MachineOperand::MO_Register: 294234285Sdim if (Src.isReg()) { 295234285Sdim Dst.setReg(Src.getReg()); 296234285Sdim } else if (Src.isImm()) { 297234285Sdim Dst.ChangeToImmediate(Src.getImm()); 298234285Sdim } else { 299234285Sdim llvm_unreachable("Unexpected src operand type"); 300234285Sdim } 301234285Sdim break; 302234285Sdim 303234285Sdim case MachineOperand::MO_Immediate: 304234285Sdim if (Src.isImm()) { 305234285Sdim Dst.setImm(Src.getImm()); 306234285Sdim } else if (Src.isReg()) { 307234285Sdim Dst.ChangeToRegister(Src.getReg(), Src.isDef(), Src.isImplicit(), 308234285Sdim Src.isKill(), Src.isDead(), Src.isUndef(), 309234285Sdim Src.isDebug()); 310234285Sdim } else { 311234285Sdim llvm_unreachable("Unexpected src operand type"); 312234285Sdim } 313234285Sdim break; 314234285Sdim 315234285Sdim default: 316234285Sdim llvm_unreachable("Unexpected dst operand type"); 317234285Sdim break; 318234285Sdim } 319234285Sdim} 320234285Sdim 321234285SdimFunctionPass *llvm::createHexagonPeephole() { 322234285Sdim return new HexagonPeephole(); 323234285Sdim} 324