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> 32261991Sdim// redundant and relies on some form of dead removal instructions, like 33234285Sdim// DCE or DIE to actually eliminate them. 34234285Sdim 35234285Sdim 36234285Sdim//===----------------------------------------------------------------------===// 37234285Sdim 38234285Sdim#include "Hexagon.h" 39234285Sdim#include "HexagonTargetMachine.h" 40234285Sdim#include "llvm/ADT/DenseMap.h" 41234285Sdim#include "llvm/ADT/Statistic.h" 42234285Sdim#include "llvm/CodeGen/MachineFunction.h" 43234285Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 44234285Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 45234285Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 46249423Sdim#include "llvm/CodeGen/Passes.h" 47249423Sdim#include "llvm/IR/Constants.h" 48249423Sdim#include "llvm/PassSupport.h" 49234285Sdim#include "llvm/Support/CommandLine.h" 50234285Sdim#include "llvm/Support/Debug.h" 51234285Sdim#include "llvm/Support/raw_ostream.h" 52249423Sdim#include "llvm/Target/TargetInstrInfo.h" 53234285Sdim#include "llvm/Target/TargetMachine.h" 54234285Sdim#include "llvm/Target/TargetRegisterInfo.h" 55234285Sdim#include <algorithm> 56234285Sdim 57234285Sdimusing namespace llvm; 58234285Sdim 59276479Sdim#define DEBUG_TYPE "hexagon-peephole" 60276479Sdim 61234285Sdimstatic cl::opt<bool> DisableHexagonPeephole("disable-hexagon-peephole", 62234285Sdim cl::Hidden, cl::ZeroOrMore, cl::init(false), 63234285Sdim cl::desc("Disable Peephole Optimization")); 64234285Sdim 65234285Sdimstatic cl::opt<bool> DisablePNotP("disable-hexagon-pnotp", 66234285Sdim cl::Hidden, cl::ZeroOrMore, cl::init(false), 67234285Sdim cl::desc("Disable Optimization of PNotP")); 68234285Sdim 69234285Sdimstatic cl::opt<bool> DisableOptSZExt("disable-hexagon-optszext", 70234285Sdim cl::Hidden, cl::ZeroOrMore, cl::init(false), 71234285Sdim cl::desc("Disable Optimization of Sign/Zero Extends")); 72234285Sdim 73251662Sdimstatic cl::opt<bool> DisableOptExtTo64("disable-hexagon-opt-ext-to-64", 74251662Sdim cl::Hidden, cl::ZeroOrMore, cl::init(false), 75251662Sdim cl::desc("Disable Optimization of extensions to i64.")); 76251662Sdim 77251662Sdimnamespace llvm { 78288943Sdim FunctionPass *createHexagonPeephole(); 79251662Sdim void initializeHexagonPeepholePass(PassRegistry&); 80251662Sdim} 81251662Sdim 82234285Sdimnamespace { 83234285Sdim struct HexagonPeephole : public MachineFunctionPass { 84234285Sdim const HexagonInstrInfo *QII; 85234285Sdim const HexagonRegisterInfo *QRI; 86234285Sdim const MachineRegisterInfo *MRI; 87234285Sdim 88234285Sdim public: 89234285Sdim static char ID; 90251662Sdim HexagonPeephole() : MachineFunctionPass(ID) { 91251662Sdim initializeHexagonPeepholePass(*PassRegistry::getPassRegistry()); 92251662Sdim } 93234285Sdim 94276479Sdim bool runOnMachineFunction(MachineFunction &MF) override; 95234285Sdim 96276479Sdim const char *getPassName() const override { 97234285Sdim return "Hexagon optimize redundant zero and size extends"; 98234285Sdim } 99234285Sdim 100276479Sdim void getAnalysisUsage(AnalysisUsage &AU) const override { 101234285Sdim MachineFunctionPass::getAnalysisUsage(AU); 102234285Sdim } 103234285Sdim 104234285Sdim private: 105234285Sdim void ChangeOpInto(MachineOperand &Dst, MachineOperand &Src); 106234285Sdim }; 107234285Sdim} 108234285Sdim 109234285Sdimchar HexagonPeephole::ID = 0; 110234285Sdim 111251662SdimINITIALIZE_PASS(HexagonPeephole, "hexagon-peephole", "Hexagon Peephole", 112251662Sdim false, false) 113251662Sdim 114234285Sdimbool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { 115280031Sdim QII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo()); 116288943Sdim QRI = MF.getSubtarget<HexagonSubtarget>().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) { 127296417Sdim 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 137280031Sdim if (!DisableOptSZExt && MI->getOpcode() == Hexagon::A2_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 && 156280031Sdim MI->getOpcode () == Hexagon::A4_combineir) { 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. 173280031Sdim if (MI->getOpcode() == Hexagon::S2_lsr_i_p) { 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] = 183296417Sdim std::make_pair(*&SrcReg, Hexagon::subreg_hireg); 184243830Sdim } 185243830Sdim 186234285Sdim // Look for P=NOT(P). 187234285Sdim if (!DisablePNotP && 188280031Sdim (MI->getOpcode() == Hexagon::C2_not)) { 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) { 273280031Sdim case Hexagon::C2_mux: 274280031Sdim case Hexagon::C2_muxii: 275234285Sdim NewOp = Op; 276234285Sdim break; 277280031Sdim case Hexagon::C2_muxri: 278280031Sdim NewOp = Hexagon::C2_muxir; 279234285Sdim break; 280280031Sdim case Hexagon::C2_muxir: 281280031Sdim NewOp = Hexagon::C2_muxri; 282234285Sdim break; 283234285Sdim } 284234285Sdim if (NewOp) { 285234285Sdim unsigned PSrc = MI->getOperand(PR).getReg(); 286234285Sdim if (unsigned POrig = PeepholeMap.lookup(PSrc)) { 287234285Sdim MI->getOperand(PR).setReg(POrig); 288234285Sdim MI->setDesc(QII->get(NewOp)); 289234285Sdim // Swap operands S1 and S2. 290234285Sdim MachineOperand Op1 = MI->getOperand(S1); 291234285Sdim MachineOperand Op2 = MI->getOperand(S2); 292234285Sdim ChangeOpInto(MI->getOperand(S1), Op2); 293234285Sdim ChangeOpInto(MI->getOperand(S2), Op1); 294234285Sdim } 295234285Sdim } // if (NewOp) 296234285Sdim } // if (!Done) 297234285Sdim 298234285Sdim } // if (!DisablePNotP) 299234285Sdim 300234285Sdim } // Instruction 301234285Sdim } // Basic Block 302234285Sdim return true; 303234285Sdim} 304234285Sdim 305234285Sdimvoid HexagonPeephole::ChangeOpInto(MachineOperand &Dst, MachineOperand &Src) { 306234285Sdim assert (&Dst != &Src && "Cannot duplicate into itself"); 307234285Sdim switch (Dst.getType()) { 308234285Sdim case MachineOperand::MO_Register: 309234285Sdim if (Src.isReg()) { 310234285Sdim Dst.setReg(Src.getReg()); 311234285Sdim } else if (Src.isImm()) { 312234285Sdim Dst.ChangeToImmediate(Src.getImm()); 313234285Sdim } else { 314234285Sdim llvm_unreachable("Unexpected src operand type"); 315234285Sdim } 316234285Sdim break; 317234285Sdim 318234285Sdim case MachineOperand::MO_Immediate: 319234285Sdim if (Src.isImm()) { 320234285Sdim Dst.setImm(Src.getImm()); 321234285Sdim } else if (Src.isReg()) { 322234285Sdim Dst.ChangeToRegister(Src.getReg(), Src.isDef(), Src.isImplicit(), 323234285Sdim Src.isKill(), Src.isDead(), Src.isUndef(), 324234285Sdim Src.isDebug()); 325234285Sdim } else { 326234285Sdim llvm_unreachable("Unexpected src operand type"); 327234285Sdim } 328234285Sdim break; 329234285Sdim 330234285Sdim default: 331234285Sdim llvm_unreachable("Unexpected dst operand type"); 332234285Sdim break; 333234285Sdim } 334234285Sdim} 335234285Sdim 336234285SdimFunctionPass *llvm::createHexagonPeephole() { 337234285Sdim return new HexagonPeephole(); 338234285Sdim} 339