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<bool> DisablePNotP("disable-hexagon-pnotp", 65234285Sdim cl::Hidden, cl::ZeroOrMore, cl::init(false), 66234285Sdim cl::desc("Disable Optimization of PNotP")); 67234285Sdim 68234285Sdimstatic cl::opt<bool> DisableOptSZExt("disable-hexagon-optszext", 69234285Sdim cl::Hidden, cl::ZeroOrMore, cl::init(false), 70234285Sdim cl::desc("Disable Optimization of Sign/Zero Extends")); 71234285Sdim 72251662Sdimstatic cl::opt<bool> DisableOptExtTo64("disable-hexagon-opt-ext-to-64", 73251662Sdim cl::Hidden, cl::ZeroOrMore, cl::init(false), 74251662Sdim cl::desc("Disable Optimization of extensions to i64.")); 75251662Sdim 76251662Sdimnamespace llvm { 77251662Sdim void initializeHexagonPeepholePass(PassRegistry&); 78251662Sdim} 79251662Sdim 80234285Sdimnamespace { 81234285Sdim struct HexagonPeephole : public MachineFunctionPass { 82234285Sdim const HexagonInstrInfo *QII; 83234285Sdim const HexagonRegisterInfo *QRI; 84234285Sdim const MachineRegisterInfo *MRI; 85234285Sdim 86234285Sdim public: 87234285Sdim static char ID; 88251662Sdim HexagonPeephole() : MachineFunctionPass(ID) { 89251662Sdim initializeHexagonPeepholePass(*PassRegistry::getPassRegistry()); 90251662Sdim } 91234285Sdim 92234285Sdim bool runOnMachineFunction(MachineFunction &MF); 93234285Sdim 94234285Sdim const char *getPassName() const { 95234285Sdim return "Hexagon optimize redundant zero and size extends"; 96234285Sdim } 97234285Sdim 98234285Sdim void getAnalysisUsage(AnalysisUsage &AU) const { 99234285Sdim MachineFunctionPass::getAnalysisUsage(AU); 100234285Sdim } 101234285Sdim 102234285Sdim private: 103234285Sdim void ChangeOpInto(MachineOperand &Dst, MachineOperand &Src); 104234285Sdim }; 105234285Sdim} 106234285Sdim 107234285Sdimchar HexagonPeephole::ID = 0; 108234285Sdim 109251662SdimINITIALIZE_PASS(HexagonPeephole, "hexagon-peephole", "Hexagon Peephole", 110251662Sdim false, false) 111251662Sdim 112234285Sdimbool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { 113234285Sdim QII = static_cast<const HexagonInstrInfo *>(MF.getTarget(). 114234285Sdim getInstrInfo()); 115234285Sdim QRI = static_cast<const HexagonRegisterInfo *>(MF.getTarget(). 116234285Sdim getRegisterInfo()); 117234285Sdim MRI = &MF.getRegInfo(); 118234285Sdim 119234285Sdim DenseMap<unsigned, unsigned> PeepholeMap; 120243830Sdim DenseMap<unsigned, std::pair<unsigned, unsigned> > PeepholeDoubleRegsMap; 121234285Sdim 122234285Sdim if (DisableHexagonPeephole) return false; 123234285Sdim 124234285Sdim // Loop over all of the basic blocks. 125234285Sdim for (MachineFunction::iterator MBBb = MF.begin(), MBBe = MF.end(); 126234285Sdim MBBb != MBBe; ++MBBb) { 127234285Sdim MachineBasicBlock* MBB = MBBb; 128234285Sdim PeepholeMap.clear(); 129243830Sdim PeepholeDoubleRegsMap.clear(); 130234285Sdim 131234285Sdim // Traverse the basic block. 132234285Sdim for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end(); 133234285Sdim ++MII) { 134234285Sdim MachineInstr *MI = MII; 135234285Sdim // Look for sign extends: 136234285Sdim // %vreg170<def> = SXTW %vreg166 137234285Sdim if (!DisableOptSZExt && MI->getOpcode() == Hexagon::SXTW) { 138234285Sdim assert (MI->getNumOperands() == 2); 139234285Sdim MachineOperand &Dst = MI->getOperand(0); 140234285Sdim MachineOperand &Src = MI->getOperand(1); 141234285Sdim unsigned DstReg = Dst.getReg(); 142234285Sdim unsigned SrcReg = Src.getReg(); 143234285Sdim // Just handle virtual registers. 144234285Sdim if (TargetRegisterInfo::isVirtualRegister(DstReg) && 145234285Sdim TargetRegisterInfo::isVirtualRegister(SrcReg)) { 146234285Sdim // Map the following: 147234285Sdim // %vreg170<def> = SXTW %vreg166 148234285Sdim // PeepholeMap[170] = vreg166 149234285Sdim PeepholeMap[DstReg] = SrcReg; 150234285Sdim } 151234285Sdim } 152234285Sdim 153251662Sdim // Look for %vreg170<def> = COMBINE_ir_V4 (0, %vreg169) 154251662Sdim // %vreg170:DoublRegs, %vreg169:IntRegs 155251662Sdim if (!DisableOptExtTo64 && 156251662Sdim MI->getOpcode () == Hexagon::COMBINE_Ir_V4) { 157251662Sdim assert (MI->getNumOperands() == 3); 158251662Sdim MachineOperand &Dst = MI->getOperand(0); 159251662Sdim MachineOperand &Src1 = MI->getOperand(1); 160251662Sdim MachineOperand &Src2 = MI->getOperand(2); 161251662Sdim if (Src1.getImm() != 0) 162251662Sdim continue; 163251662Sdim unsigned DstReg = Dst.getReg(); 164251662Sdim unsigned SrcReg = Src2.getReg(); 165251662Sdim PeepholeMap[DstReg] = SrcReg; 166251662Sdim } 167251662Sdim 168243830Sdim // Look for this sequence below 169243830Sdim // %vregDoubleReg1 = LSRd_ri %vregDoubleReg0, 32 170243830Sdim // %vregIntReg = COPY %vregDoubleReg1:subreg_loreg. 171243830Sdim // and convert into 172243830Sdim // %vregIntReg = COPY %vregDoubleReg0:subreg_hireg. 173243830Sdim if (MI->getOpcode() == Hexagon::LSRd_ri) { 174243830Sdim assert(MI->getNumOperands() == 3); 175243830Sdim MachineOperand &Dst = MI->getOperand(0); 176243830Sdim MachineOperand &Src1 = MI->getOperand(1); 177243830Sdim MachineOperand &Src2 = MI->getOperand(2); 178243830Sdim if (Src2.getImm() != 32) 179243830Sdim continue; 180243830Sdim unsigned DstReg = Dst.getReg(); 181243830Sdim unsigned SrcReg = Src1.getReg(); 182243830Sdim PeepholeDoubleRegsMap[DstReg] = 183243830Sdim std::make_pair(*&SrcReg, 1/*Hexagon::subreg_hireg*/); 184243830Sdim } 185243830Sdim 186234285Sdim // Look for P=NOT(P). 187234285Sdim if (!DisablePNotP && 188234285Sdim (MI->getOpcode() == Hexagon::NOT_p)) { 189234285Sdim assert (MI->getNumOperands() == 2); 190234285Sdim MachineOperand &Dst = MI->getOperand(0); 191234285Sdim MachineOperand &Src = MI->getOperand(1); 192234285Sdim unsigned DstReg = Dst.getReg(); 193234285Sdim unsigned SrcReg = Src.getReg(); 194234285Sdim // Just handle virtual registers. 195234285Sdim if (TargetRegisterInfo::isVirtualRegister(DstReg) && 196234285Sdim TargetRegisterInfo::isVirtualRegister(SrcReg)) { 197234285Sdim // Map the following: 198234285Sdim // %vreg170<def> = NOT_xx %vreg166 199234285Sdim // PeepholeMap[170] = vreg166 200234285Sdim PeepholeMap[DstReg] = SrcReg; 201234285Sdim } 202234285Sdim } 203234285Sdim 204234285Sdim // Look for copy: 205234285Sdim // %vreg176<def> = COPY %vreg170:subreg_loreg 206234285Sdim if (!DisableOptSZExt && MI->isCopy()) { 207234285Sdim assert (MI->getNumOperands() == 2); 208234285Sdim MachineOperand &Dst = MI->getOperand(0); 209234285Sdim MachineOperand &Src = MI->getOperand(1); 210234285Sdim 211234285Sdim // Make sure we are copying the lower 32 bits. 212234285Sdim if (Src.getSubReg() != Hexagon::subreg_loreg) 213234285Sdim continue; 214234285Sdim 215234285Sdim unsigned DstReg = Dst.getReg(); 216234285Sdim unsigned SrcReg = Src.getReg(); 217234285Sdim if (TargetRegisterInfo::isVirtualRegister(DstReg) && 218234285Sdim TargetRegisterInfo::isVirtualRegister(SrcReg)) { 219234285Sdim // Try to find in the map. 220234285Sdim if (unsigned PeepholeSrc = PeepholeMap.lookup(SrcReg)) { 221234285Sdim // Change the 1st operand. 222234285Sdim MI->RemoveOperand(1); 223234285Sdim MI->addOperand(MachineOperand::CreateReg(PeepholeSrc, false)); 224243830Sdim } else { 225243830Sdim DenseMap<unsigned, std::pair<unsigned, unsigned> >::iterator DI = 226243830Sdim PeepholeDoubleRegsMap.find(SrcReg); 227243830Sdim if (DI != PeepholeDoubleRegsMap.end()) { 228243830Sdim std::pair<unsigned,unsigned> PeepholeSrc = DI->second; 229243830Sdim MI->RemoveOperand(1); 230243830Sdim MI->addOperand(MachineOperand::CreateReg(PeepholeSrc.first, 231243830Sdim false /*isDef*/, 232243830Sdim false /*isImp*/, 233243830Sdim false /*isKill*/, 234243830Sdim false /*isDead*/, 235243830Sdim false /*isUndef*/, 236243830Sdim false /*isEarlyClobber*/, 237243830Sdim PeepholeSrc.second)); 238243830Sdim } 239234285Sdim } 240234285Sdim } 241234285Sdim } 242234285Sdim 243234285Sdim // Look for Predicated instructions. 244234285Sdim if (!DisablePNotP) { 245234285Sdim bool Done = false; 246234285Sdim if (QII->isPredicated(MI)) { 247234285Sdim MachineOperand &Op0 = MI->getOperand(0); 248234285Sdim unsigned Reg0 = Op0.getReg(); 249234285Sdim const TargetRegisterClass *RC0 = MRI->getRegClass(Reg0); 250234285Sdim if (RC0->getID() == Hexagon::PredRegsRegClassID) { 251234285Sdim // Handle instructions that have a prediate register in op0 252234285Sdim // (most cases of predicable instructions). 253234285Sdim if (TargetRegisterInfo::isVirtualRegister(Reg0)) { 254234285Sdim // Try to find in the map. 255234285Sdim if (unsigned PeepholeSrc = PeepholeMap.lookup(Reg0)) { 256234285Sdim // Change the 1st operand and, flip the opcode. 257234285Sdim MI->getOperand(0).setReg(PeepholeSrc); 258234285Sdim int NewOp = QII->getInvertedPredicatedOpcode(MI->getOpcode()); 259234285Sdim MI->setDesc(QII->get(NewOp)); 260234285Sdim Done = true; 261234285Sdim } 262234285Sdim } 263234285Sdim } 264234285Sdim } 265234285Sdim 266234285Sdim if (!Done) { 267234285Sdim // Handle special instructions. 268234285Sdim unsigned Op = MI->getOpcode(); 269234285Sdim unsigned NewOp = 0; 270234285Sdim unsigned PR = 1, S1 = 2, S2 = 3; // Operand indices. 271234285Sdim 272234285Sdim switch (Op) { 273234285Sdim case Hexagon::TFR_condset_rr: 274234285Sdim case Hexagon::TFR_condset_ii: 275234285Sdim case Hexagon::MUX_ii: 276234285Sdim case Hexagon::MUX_rr: 277234285Sdim NewOp = Op; 278234285Sdim break; 279234285Sdim case Hexagon::TFR_condset_ri: 280234285Sdim NewOp = Hexagon::TFR_condset_ir; 281234285Sdim break; 282234285Sdim case Hexagon::TFR_condset_ir: 283234285Sdim NewOp = Hexagon::TFR_condset_ri; 284234285Sdim break; 285234285Sdim case Hexagon::MUX_ri: 286234285Sdim NewOp = Hexagon::MUX_ir; 287234285Sdim break; 288234285Sdim case Hexagon::MUX_ir: 289234285Sdim NewOp = Hexagon::MUX_ri; 290234285Sdim break; 291234285Sdim } 292234285Sdim if (NewOp) { 293234285Sdim unsigned PSrc = MI->getOperand(PR).getReg(); 294234285Sdim if (unsigned POrig = PeepholeMap.lookup(PSrc)) { 295234285Sdim MI->getOperand(PR).setReg(POrig); 296234285Sdim MI->setDesc(QII->get(NewOp)); 297234285Sdim // Swap operands S1 and S2. 298234285Sdim MachineOperand Op1 = MI->getOperand(S1); 299234285Sdim MachineOperand Op2 = MI->getOperand(S2); 300234285Sdim ChangeOpInto(MI->getOperand(S1), Op2); 301234285Sdim ChangeOpInto(MI->getOperand(S2), Op1); 302234285Sdim } 303234285Sdim } // if (NewOp) 304234285Sdim } // if (!Done) 305234285Sdim 306234285Sdim } // if (!DisablePNotP) 307234285Sdim 308234285Sdim } // Instruction 309234285Sdim } // Basic Block 310234285Sdim return true; 311234285Sdim} 312234285Sdim 313234285Sdimvoid HexagonPeephole::ChangeOpInto(MachineOperand &Dst, MachineOperand &Src) { 314234285Sdim assert (&Dst != &Src && "Cannot duplicate into itself"); 315234285Sdim switch (Dst.getType()) { 316234285Sdim case MachineOperand::MO_Register: 317234285Sdim if (Src.isReg()) { 318234285Sdim Dst.setReg(Src.getReg()); 319234285Sdim } else if (Src.isImm()) { 320234285Sdim Dst.ChangeToImmediate(Src.getImm()); 321234285Sdim } else { 322234285Sdim llvm_unreachable("Unexpected src operand type"); 323234285Sdim } 324234285Sdim break; 325234285Sdim 326234285Sdim case MachineOperand::MO_Immediate: 327234285Sdim if (Src.isImm()) { 328234285Sdim Dst.setImm(Src.getImm()); 329234285Sdim } else if (Src.isReg()) { 330234285Sdim Dst.ChangeToRegister(Src.getReg(), Src.isDef(), Src.isImplicit(), 331234285Sdim Src.isKill(), Src.isDead(), Src.isUndef(), 332234285Sdim Src.isDebug()); 333234285Sdim } else { 334234285Sdim llvm_unreachable("Unexpected src operand type"); 335234285Sdim } 336234285Sdim break; 337234285Sdim 338234285Sdim default: 339234285Sdim llvm_unreachable("Unexpected dst operand type"); 340234285Sdim break; 341234285Sdim } 342234285Sdim} 343234285Sdim 344234285SdimFunctionPass *llvm::createHexagonPeephole() { 345234285Sdim return new HexagonPeephole(); 346234285Sdim} 347