| //===-- HexagonPeephole.cpp - Hexagon Peephole Optimiztions ---------------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | // This peephole pass optimizes in the following cases. | 
 | // 1. Optimizes redundant sign extends for the following case | 
 | //    Transform the following pattern | 
 | //    %170 = SXTW %166 | 
 | //    ... | 
 | //    %176 = COPY %170:isub_lo | 
 | // | 
 | //    Into | 
 | //    %176 = COPY %166 | 
 | // | 
 | //  2. Optimizes redundant negation of predicates. | 
 | //     %15 = CMPGTrr %6, %2 | 
 | //     ... | 
 | //     %16 = NOT_p killed %15 | 
 | //     ... | 
 | //     JMP_c killed %16, <%bb.1>, implicit dead %pc | 
 | // | 
 | //     Into | 
 | //     %15 = CMPGTrr %6, %2; | 
 | //     ... | 
 | //     JMP_cNot killed %15, <%bb.1>, implicit dead %pc; | 
 | // | 
 | // Note: The peephole pass makes the instrucstions like | 
 | // %170 = SXTW %166 or %16 = NOT_p killed %15 | 
 | // redundant and relies on some form of dead removal instructions, like | 
 | // DCE or DIE to actually eliminate them. | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "Hexagon.h" | 
 | #include "HexagonTargetMachine.h" | 
 | #include "llvm/ADT/DenseMap.h" | 
 | #include "llvm/ADT/Statistic.h" | 
 | #include "llvm/CodeGen/MachineFunction.h" | 
 | #include "llvm/CodeGen/MachineFunctionPass.h" | 
 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
 | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
 | #include "llvm/CodeGen/Passes.h" | 
 | #include "llvm/CodeGen/TargetInstrInfo.h" | 
 | #include "llvm/CodeGen/TargetRegisterInfo.h" | 
 | #include "llvm/IR/Constants.h" | 
 | #include "llvm/PassSupport.h" | 
 | #include "llvm/Support/CommandLine.h" | 
 | #include "llvm/Support/Debug.h" | 
 | #include "llvm/Support/raw_ostream.h" | 
 | #include "llvm/Target/TargetMachine.h" | 
 | #include <algorithm> | 
 |  | 
 | using namespace llvm; | 
 |  | 
 | #define DEBUG_TYPE "hexagon-peephole" | 
 |  | 
 | static cl::opt<bool> DisableHexagonPeephole("disable-hexagon-peephole", | 
 |     cl::Hidden, cl::ZeroOrMore, cl::init(false), | 
 |     cl::desc("Disable Peephole Optimization")); | 
 |  | 
 | static cl::opt<bool> DisablePNotP("disable-hexagon-pnotp", | 
 |     cl::Hidden, cl::ZeroOrMore, cl::init(false), | 
 |     cl::desc("Disable Optimization of PNotP")); | 
 |  | 
 | static cl::opt<bool> DisableOptSZExt("disable-hexagon-optszext", | 
 |     cl::Hidden, cl::ZeroOrMore, cl::init(true), | 
 |     cl::desc("Disable Optimization of Sign/Zero Extends")); | 
 |  | 
 | static cl::opt<bool> DisableOptExtTo64("disable-hexagon-opt-ext-to-64", | 
 |     cl::Hidden, cl::ZeroOrMore, cl::init(true), | 
 |     cl::desc("Disable Optimization of extensions to i64.")); | 
 |  | 
 | namespace llvm { | 
 |   FunctionPass *createHexagonPeephole(); | 
 |   void initializeHexagonPeepholePass(PassRegistry&); | 
 | } | 
 |  | 
 | namespace { | 
 |   struct HexagonPeephole : public MachineFunctionPass { | 
 |     const HexagonInstrInfo    *QII; | 
 |     const HexagonRegisterInfo *QRI; | 
 |     const MachineRegisterInfo *MRI; | 
 |  | 
 |   public: | 
 |     static char ID; | 
 |     HexagonPeephole() : MachineFunctionPass(ID) { | 
 |       initializeHexagonPeepholePass(*PassRegistry::getPassRegistry()); | 
 |     } | 
 |  | 
 |     bool runOnMachineFunction(MachineFunction &MF) override; | 
 |  | 
 |     StringRef getPassName() const override { | 
 |       return "Hexagon optimize redundant zero and size extends"; | 
 |     } | 
 |  | 
 |     void getAnalysisUsage(AnalysisUsage &AU) const override { | 
 |       MachineFunctionPass::getAnalysisUsage(AU); | 
 |     } | 
 |   }; | 
 | } | 
 |  | 
 | char HexagonPeephole::ID = 0; | 
 |  | 
 | INITIALIZE_PASS(HexagonPeephole, "hexagon-peephole", "Hexagon Peephole", | 
 |                 false, false) | 
 |  | 
 | bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { | 
 |   if (skipFunction(MF.getFunction())) | 
 |     return false; | 
 |  | 
 |   QII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo()); | 
 |   QRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo(); | 
 |   MRI = &MF.getRegInfo(); | 
 |  | 
 |   DenseMap<unsigned, unsigned> PeepholeMap; | 
 |   DenseMap<unsigned, std::pair<unsigned, unsigned> > PeepholeDoubleRegsMap; | 
 |  | 
 |   if (DisableHexagonPeephole) return false; | 
 |  | 
 |   // Loop over all of the basic blocks. | 
 |   for (MachineFunction::iterator MBBb = MF.begin(), MBBe = MF.end(); | 
 |        MBBb != MBBe; ++MBBb) { | 
 |     MachineBasicBlock *MBB = &*MBBb; | 
 |     PeepholeMap.clear(); | 
 |     PeepholeDoubleRegsMap.clear(); | 
 |  | 
 |     // Traverse the basic block. | 
 |     for (auto I = MBB->begin(), E = MBB->end(), NextI = I; I != E; I = NextI) { | 
 |       NextI = std::next(I); | 
 |       MachineInstr &MI = *I; | 
 |       // Look for sign extends: | 
 |       // %170 = SXTW %166 | 
 |       if (!DisableOptSZExt && MI.getOpcode() == Hexagon::A2_sxtw) { | 
 |         assert(MI.getNumOperands() == 2); | 
 |         MachineOperand &Dst = MI.getOperand(0); | 
 |         MachineOperand &Src = MI.getOperand(1); | 
 |         unsigned DstReg = Dst.getReg(); | 
 |         unsigned SrcReg = Src.getReg(); | 
 |         // Just handle virtual registers. | 
 |         if (TargetRegisterInfo::isVirtualRegister(DstReg) && | 
 |             TargetRegisterInfo::isVirtualRegister(SrcReg)) { | 
 |           // Map the following: | 
 |           // %170 = SXTW %166 | 
 |           // PeepholeMap[170] = %166 | 
 |           PeepholeMap[DstReg] = SrcReg; | 
 |         } | 
 |       } | 
 |  | 
 |       // Look for  %170 = COMBINE_ir_V4 (0, %169) | 
 |       // %170:DoublRegs, %169:IntRegs | 
 |       if (!DisableOptExtTo64 && MI.getOpcode() == Hexagon::A4_combineir) { | 
 |         assert(MI.getNumOperands() == 3); | 
 |         MachineOperand &Dst = MI.getOperand(0); | 
 |         MachineOperand &Src1 = MI.getOperand(1); | 
 |         MachineOperand &Src2 = MI.getOperand(2); | 
 |         if (Src1.getImm() != 0) | 
 |           continue; | 
 |         unsigned DstReg = Dst.getReg(); | 
 |         unsigned SrcReg = Src2.getReg(); | 
 |         PeepholeMap[DstReg] = SrcReg; | 
 |       } | 
 |  | 
 |       // Look for this sequence below | 
 |       // %DoubleReg1 = LSRd_ri %DoubleReg0, 32 | 
 |       // %IntReg = COPY %DoubleReg1:isub_lo. | 
 |       // and convert into | 
 |       // %IntReg = COPY %DoubleReg0:isub_hi. | 
 |       if (MI.getOpcode() == Hexagon::S2_lsr_i_p) { | 
 |         assert(MI.getNumOperands() == 3); | 
 |         MachineOperand &Dst = MI.getOperand(0); | 
 |         MachineOperand &Src1 = MI.getOperand(1); | 
 |         MachineOperand &Src2 = MI.getOperand(2); | 
 |         if (Src2.getImm() != 32) | 
 |           continue; | 
 |         unsigned DstReg = Dst.getReg(); | 
 |         unsigned SrcReg = Src1.getReg(); | 
 |         PeepholeDoubleRegsMap[DstReg] = | 
 |           std::make_pair(*&SrcReg, Hexagon::isub_hi); | 
 |       } | 
 |  | 
 |       // Look for P=NOT(P). | 
 |       if (!DisablePNotP && MI.getOpcode() == Hexagon::C2_not) { | 
 |         assert(MI.getNumOperands() == 2); | 
 |         MachineOperand &Dst = MI.getOperand(0); | 
 |         MachineOperand &Src = MI.getOperand(1); | 
 |         unsigned DstReg = Dst.getReg(); | 
 |         unsigned SrcReg = Src.getReg(); | 
 |         // Just handle virtual registers. | 
 |         if (TargetRegisterInfo::isVirtualRegister(DstReg) && | 
 |             TargetRegisterInfo::isVirtualRegister(SrcReg)) { | 
 |           // Map the following: | 
 |           // %170 = NOT_xx %166 | 
 |           // PeepholeMap[170] = %166 | 
 |           PeepholeMap[DstReg] = SrcReg; | 
 |         } | 
 |       } | 
 |  | 
 |       // Look for copy: | 
 |       // %176 = COPY %170:isub_lo | 
 |       if (!DisableOptSZExt && MI.isCopy()) { | 
 |         assert(MI.getNumOperands() == 2); | 
 |         MachineOperand &Dst = MI.getOperand(0); | 
 |         MachineOperand &Src = MI.getOperand(1); | 
 |  | 
 |         // Make sure we are copying the lower 32 bits. | 
 |         if (Src.getSubReg() != Hexagon::isub_lo) | 
 |           continue; | 
 |  | 
 |         unsigned DstReg = Dst.getReg(); | 
 |         unsigned SrcReg = Src.getReg(); | 
 |         if (TargetRegisterInfo::isVirtualRegister(DstReg) && | 
 |             TargetRegisterInfo::isVirtualRegister(SrcReg)) { | 
 |           // Try to find in the map. | 
 |           if (unsigned PeepholeSrc = PeepholeMap.lookup(SrcReg)) { | 
 |             // Change the 1st operand. | 
 |             MI.RemoveOperand(1); | 
 |             MI.addOperand(MachineOperand::CreateReg(PeepholeSrc, false)); | 
 |           } else  { | 
 |             DenseMap<unsigned, std::pair<unsigned, unsigned> >::iterator DI = | 
 |               PeepholeDoubleRegsMap.find(SrcReg); | 
 |             if (DI != PeepholeDoubleRegsMap.end()) { | 
 |               std::pair<unsigned,unsigned> PeepholeSrc = DI->second; | 
 |               MI.RemoveOperand(1); | 
 |               MI.addOperand(MachineOperand::CreateReg( | 
 |                   PeepholeSrc.first, false /*isDef*/, false /*isImp*/, | 
 |                   false /*isKill*/, false /*isDead*/, false /*isUndef*/, | 
 |                   false /*isEarlyClobber*/, PeepholeSrc.second)); | 
 |             } | 
 |           } | 
 |         } | 
 |       } | 
 |  | 
 |       // Look for Predicated instructions. | 
 |       if (!DisablePNotP) { | 
 |         bool Done = false; | 
 |         if (QII->isPredicated(MI)) { | 
 |           MachineOperand &Op0 = MI.getOperand(0); | 
 |           unsigned Reg0 = Op0.getReg(); | 
 |           const TargetRegisterClass *RC0 = MRI->getRegClass(Reg0); | 
 |           if (RC0->getID() == Hexagon::PredRegsRegClassID) { | 
 |             // Handle instructions that have a prediate register in op0 | 
 |             // (most cases of predicable instructions). | 
 |             if (TargetRegisterInfo::isVirtualRegister(Reg0)) { | 
 |               // Try to find in the map. | 
 |               if (unsigned PeepholeSrc = PeepholeMap.lookup(Reg0)) { | 
 |                 // Change the 1st operand and, flip the opcode. | 
 |                 MI.getOperand(0).setReg(PeepholeSrc); | 
 |                 MRI->clearKillFlags(PeepholeSrc); | 
 |                 int NewOp = QII->getInvertedPredicatedOpcode(MI.getOpcode()); | 
 |                 MI.setDesc(QII->get(NewOp)); | 
 |                 Done = true; | 
 |               } | 
 |             } | 
 |           } | 
 |         } | 
 |  | 
 |         if (!Done) { | 
 |           // Handle special instructions. | 
 |           unsigned Op = MI.getOpcode(); | 
 |           unsigned NewOp = 0; | 
 |           unsigned PR = 1, S1 = 2, S2 = 3;   // Operand indices. | 
 |  | 
 |           switch (Op) { | 
 |             case Hexagon::C2_mux: | 
 |             case Hexagon::C2_muxii: | 
 |               NewOp = Op; | 
 |               break; | 
 |             case Hexagon::C2_muxri: | 
 |               NewOp = Hexagon::C2_muxir; | 
 |               break; | 
 |             case Hexagon::C2_muxir: | 
 |               NewOp = Hexagon::C2_muxri; | 
 |               break; | 
 |           } | 
 |           if (NewOp) { | 
 |             unsigned PSrc = MI.getOperand(PR).getReg(); | 
 |             if (unsigned POrig = PeepholeMap.lookup(PSrc)) { | 
 |               BuildMI(*MBB, MI.getIterator(), MI.getDebugLoc(), | 
 |                       QII->get(NewOp), MI.getOperand(0).getReg()) | 
 |                 .addReg(POrig) | 
 |                 .add(MI.getOperand(S2)) | 
 |                 .add(MI.getOperand(S1)); | 
 |               MRI->clearKillFlags(POrig); | 
 |               MI.eraseFromParent(); | 
 |             } | 
 |           } // if (NewOp) | 
 |         } // if (!Done) | 
 |  | 
 |       } // if (!DisablePNotP) | 
 |  | 
 |     } // Instruction | 
 |   } // Basic Block | 
 |   return true; | 
 | } | 
 |  | 
 | FunctionPass *llvm::createHexagonPeephole() { | 
 |   return new HexagonPeephole(); | 
 | } |