16995e5daSNemanja Ivanovic //===--------- PPCPreEmitPeephole.cpp - Late peephole optimizations -------===// 26995e5daSNemanja Ivanovic // 36995e5daSNemanja Ivanovic // The LLVM Compiler Infrastructure 46995e5daSNemanja Ivanovic // 56995e5daSNemanja Ivanovic // This file is distributed under the University of Illinois Open Source 66995e5daSNemanja Ivanovic // License. See LICENSE.TXT for details. 76995e5daSNemanja Ivanovic // 86995e5daSNemanja Ivanovic //===----------------------------------------------------------------------===// 96995e5daSNemanja Ivanovic // 106995e5daSNemanja Ivanovic // A pre-emit peephole for catching opportunities introduced by late passes such 116995e5daSNemanja Ivanovic // as MachineBlockPlacement. 126995e5daSNemanja Ivanovic // 136995e5daSNemanja Ivanovic //===----------------------------------------------------------------------===// 146995e5daSNemanja Ivanovic 156995e5daSNemanja Ivanovic #include "PPC.h" 166995e5daSNemanja Ivanovic #include "PPCInstrInfo.h" 176995e5daSNemanja Ivanovic #include "PPCSubtarget.h" 186995e5daSNemanja Ivanovic #include "llvm/ADT/DenseMap.h" 196995e5daSNemanja Ivanovic #include "llvm/ADT/Statistic.h" 206995e5daSNemanja Ivanovic #include "llvm/CodeGen/LivePhysRegs.h" 2120982f09SHiroshi Inoue #include "llvm/CodeGen/MachineBasicBlock.h" 226995e5daSNemanja Ivanovic #include "llvm/CodeGen/MachineFunctionPass.h" 236995e5daSNemanja Ivanovic #include "llvm/CodeGen/MachineInstrBuilder.h" 246995e5daSNemanja Ivanovic #include "llvm/CodeGen/MachineRegisterInfo.h" 256995e5daSNemanja Ivanovic #include "llvm/Support/CommandLine.h" 266995e5daSNemanja Ivanovic #include "llvm/ADT/Statistic.h" 276995e5daSNemanja Ivanovic #include "llvm/Support/Debug.h" 286995e5daSNemanja Ivanovic 296995e5daSNemanja Ivanovic using namespace llvm; 306995e5daSNemanja Ivanovic 316995e5daSNemanja Ivanovic #define DEBUG_TYPE "ppc-pre-emit-peephole" 326995e5daSNemanja Ivanovic 336995e5daSNemanja Ivanovic STATISTIC(NumRRConvertedInPreEmit, 346995e5daSNemanja Ivanovic "Number of r+r instructions converted to r+i in pre-emit peephole"); 356995e5daSNemanja Ivanovic STATISTIC(NumRemovedInPreEmit, 366995e5daSNemanja Ivanovic "Number of instructions deleted in pre-emit peephole"); 374c0b110eSNemanja Ivanovic STATISTIC(NumberOfSelfCopies, 384c0b110eSNemanja Ivanovic "Number of self copy instructions eliminated"); 396995e5daSNemanja Ivanovic 406995e5daSNemanja Ivanovic static cl::opt<bool> 414e1f5e07SNemanja Ivanovic RunPreEmitPeephole("ppc-late-peephole", cl::Hidden, cl::init(true), 426995e5daSNemanja Ivanovic cl::desc("Run pre-emit peephole optimizations.")); 436995e5daSNemanja Ivanovic 446995e5daSNemanja Ivanovic namespace { 456995e5daSNemanja Ivanovic class PPCPreEmitPeephole : public MachineFunctionPass { 466995e5daSNemanja Ivanovic public: 476995e5daSNemanja Ivanovic static char ID; 486995e5daSNemanja Ivanovic PPCPreEmitPeephole() : MachineFunctionPass(ID) { 496995e5daSNemanja Ivanovic initializePPCPreEmitPeepholePass(*PassRegistry::getPassRegistry()); 506995e5daSNemanja Ivanovic } 516995e5daSNemanja Ivanovic 526995e5daSNemanja Ivanovic void getAnalysisUsage(AnalysisUsage &AU) const override { 536995e5daSNemanja Ivanovic MachineFunctionPass::getAnalysisUsage(AU); 546995e5daSNemanja Ivanovic } 556995e5daSNemanja Ivanovic 566995e5daSNemanja Ivanovic MachineFunctionProperties getRequiredProperties() const override { 576995e5daSNemanja Ivanovic return MachineFunctionProperties().set( 586995e5daSNemanja Ivanovic MachineFunctionProperties::Property::NoVRegs); 596995e5daSNemanja Ivanovic } 606995e5daSNemanja Ivanovic 616995e5daSNemanja Ivanovic bool runOnMachineFunction(MachineFunction &MF) override { 62f1caa283SMatthias Braun if (skipFunction(MF.getFunction()) || !RunPreEmitPeephole) 636995e5daSNemanja Ivanovic return false; 646995e5daSNemanja Ivanovic bool Changed = false; 656995e5daSNemanja Ivanovic const PPCInstrInfo *TII = MF.getSubtarget<PPCSubtarget>().getInstrInfo(); 6620982f09SHiroshi Inoue const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 676995e5daSNemanja Ivanovic SmallVector<MachineInstr *, 4> InstrsToErase; 686995e5daSNemanja Ivanovic for (MachineBasicBlock &MBB : MF) { 696995e5daSNemanja Ivanovic for (MachineInstr &MI : MBB) { 704c0b110eSNemanja Ivanovic unsigned Opc = MI.getOpcode(); 714c0b110eSNemanja Ivanovic // Detect self copies - these can result from running AADB. 724c0b110eSNemanja Ivanovic if (PPCInstrInfo::isSameClassPhysRegCopy(Opc)) { 734c0b110eSNemanja Ivanovic const MCInstrDesc &MCID = TII->get(Opc); 744c0b110eSNemanja Ivanovic if (MCID.getNumOperands() == 3 && 754c0b110eSNemanja Ivanovic MI.getOperand(0).getReg() == MI.getOperand(1).getReg() && 764c0b110eSNemanja Ivanovic MI.getOperand(0).getReg() == MI.getOperand(2).getReg()) { 774c0b110eSNemanja Ivanovic NumberOfSelfCopies++; 784c0b110eSNemanja Ivanovic LLVM_DEBUG(dbgs() << "Deleting self-copy instruction: "); 794c0b110eSNemanja Ivanovic LLVM_DEBUG(MI.dump()); 804c0b110eSNemanja Ivanovic InstrsToErase.push_back(&MI); 814c0b110eSNemanja Ivanovic continue; 824c0b110eSNemanja Ivanovic } 834c0b110eSNemanja Ivanovic else if (MCID.getNumOperands() == 2 && 844c0b110eSNemanja Ivanovic MI.getOperand(0).getReg() == MI.getOperand(1).getReg()) { 854c0b110eSNemanja Ivanovic NumberOfSelfCopies++; 864c0b110eSNemanja Ivanovic LLVM_DEBUG(dbgs() << "Deleting self-copy instruction: "); 874c0b110eSNemanja Ivanovic LLVM_DEBUG(MI.dump()); 884c0b110eSNemanja Ivanovic InstrsToErase.push_back(&MI); 894c0b110eSNemanja Ivanovic continue; 904c0b110eSNemanja Ivanovic } 914c0b110eSNemanja Ivanovic } 926995e5daSNemanja Ivanovic MachineInstr *DefMIToErase = nullptr; 936995e5daSNemanja Ivanovic if (TII->convertToImmediateForm(MI, &DefMIToErase)) { 946995e5daSNemanja Ivanovic Changed = true; 956995e5daSNemanja Ivanovic NumRRConvertedInPreEmit++; 96d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Converted instruction to imm form: "); 97d34e60caSNicola Zaghen LLVM_DEBUG(MI.dump()); 986995e5daSNemanja Ivanovic if (DefMIToErase) { 996995e5daSNemanja Ivanovic InstrsToErase.push_back(DefMIToErase); 1006995e5daSNemanja Ivanovic } 1016995e5daSNemanja Ivanovic } 1026995e5daSNemanja Ivanovic } 10320982f09SHiroshi Inoue 10420982f09SHiroshi Inoue // Eliminate conditional branch based on a constant CR bit by 10520982f09SHiroshi Inoue // CRSET or CRUNSET. We eliminate the conditional branch or 10620982f09SHiroshi Inoue // convert it into an unconditional branch. Also, if the CR bit 10720982f09SHiroshi Inoue // is not used by other instructions, we eliminate CRSET as well. 10820982f09SHiroshi Inoue auto I = MBB.getFirstInstrTerminator(); 10920982f09SHiroshi Inoue if (I == MBB.instr_end()) 11020982f09SHiroshi Inoue continue; 11120982f09SHiroshi Inoue MachineInstr *Br = &*I; 11220982f09SHiroshi Inoue if (Br->getOpcode() != PPC::BC && Br->getOpcode() != PPC::BCn) 11320982f09SHiroshi Inoue continue; 11420982f09SHiroshi Inoue MachineInstr *CRSetMI = nullptr; 11520982f09SHiroshi Inoue unsigned CRBit = Br->getOperand(0).getReg(); 11620982f09SHiroshi Inoue unsigned CRReg = getCRFromCRBit(CRBit); 11720982f09SHiroshi Inoue bool SeenUse = false; 11820982f09SHiroshi Inoue MachineBasicBlock::reverse_iterator It = Br, Er = MBB.rend(); 11920982f09SHiroshi Inoue for (It++; It != Er; It++) { 12020982f09SHiroshi Inoue if (It->modifiesRegister(CRBit, TRI)) { 12120982f09SHiroshi Inoue if ((It->getOpcode() == PPC::CRUNSET || 12220982f09SHiroshi Inoue It->getOpcode() == PPC::CRSET) && 12320982f09SHiroshi Inoue It->getOperand(0).getReg() == CRBit) 12420982f09SHiroshi Inoue CRSetMI = &*It; 12520982f09SHiroshi Inoue break; 12620982f09SHiroshi Inoue } 12720982f09SHiroshi Inoue if (It->readsRegister(CRBit, TRI)) 12820982f09SHiroshi Inoue SeenUse = true; 12920982f09SHiroshi Inoue } 13020982f09SHiroshi Inoue if (!CRSetMI) continue; 13120982f09SHiroshi Inoue 13220982f09SHiroshi Inoue unsigned CRSetOp = CRSetMI->getOpcode(); 13320982f09SHiroshi Inoue if ((Br->getOpcode() == PPC::BCn && CRSetOp == PPC::CRSET) || 13420982f09SHiroshi Inoue (Br->getOpcode() == PPC::BC && CRSetOp == PPC::CRUNSET)) { 13520982f09SHiroshi Inoue // Remove this branch since it cannot be taken. 13620982f09SHiroshi Inoue InstrsToErase.push_back(Br); 13720982f09SHiroshi Inoue MBB.removeSuccessor(Br->getOperand(1).getMBB()); 13820982f09SHiroshi Inoue } 13920982f09SHiroshi Inoue else { 14020982f09SHiroshi Inoue // This conditional branch is always taken. So, remove all branches 14120982f09SHiroshi Inoue // and insert an unconditional branch to the destination of this. 14220982f09SHiroshi Inoue MachineBasicBlock::iterator It = Br, Er = MBB.end(); 143*ecc89b76SWei Mi for (; It != Er; It++) { 14420982f09SHiroshi Inoue if (It->isDebugInstr()) continue; 14520982f09SHiroshi Inoue assert(It->isTerminator() && "Non-terminator after a terminator"); 14620982f09SHiroshi Inoue InstrsToErase.push_back(&*It); 14720982f09SHiroshi Inoue } 14820982f09SHiroshi Inoue if (!MBB.isLayoutSuccessor(Br->getOperand(1).getMBB())) { 14920982f09SHiroshi Inoue ArrayRef<MachineOperand> NoCond; 15020982f09SHiroshi Inoue TII->insertBranch(MBB, Br->getOperand(1).getMBB(), nullptr, 15120982f09SHiroshi Inoue NoCond, Br->getDebugLoc()); 15220982f09SHiroshi Inoue } 15320982f09SHiroshi Inoue for (auto &Succ : MBB.successors()) 15420982f09SHiroshi Inoue if (Succ != Br->getOperand(1).getMBB()) { 15520982f09SHiroshi Inoue MBB.removeSuccessor(Succ); 15620982f09SHiroshi Inoue break; 15720982f09SHiroshi Inoue } 15820982f09SHiroshi Inoue } 15920982f09SHiroshi Inoue 16020982f09SHiroshi Inoue // If the CRBit is not used by another instruction, we can eliminate 16120982f09SHiroshi Inoue // CRSET/CRUNSET instruction. 16220982f09SHiroshi Inoue if (!SeenUse) { 16320982f09SHiroshi Inoue // We need to check use of the CRBit in successors. 16420982f09SHiroshi Inoue for (auto &SuccMBB : MBB.successors()) 16520982f09SHiroshi Inoue if (SuccMBB->isLiveIn(CRBit) || SuccMBB->isLiveIn(CRReg)) { 16620982f09SHiroshi Inoue SeenUse = true; 16720982f09SHiroshi Inoue break; 16820982f09SHiroshi Inoue } 16920982f09SHiroshi Inoue if (!SeenUse) 17020982f09SHiroshi Inoue InstrsToErase.push_back(CRSetMI); 17120982f09SHiroshi Inoue } 1726995e5daSNemanja Ivanovic } 1736995e5daSNemanja Ivanovic for (MachineInstr *MI : InstrsToErase) { 174d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "PPC pre-emit peephole: erasing instruction: "); 175d34e60caSNicola Zaghen LLVM_DEBUG(MI->dump()); 1766995e5daSNemanja Ivanovic MI->eraseFromParent(); 1776995e5daSNemanja Ivanovic NumRemovedInPreEmit++; 1786995e5daSNemanja Ivanovic } 1796995e5daSNemanja Ivanovic return Changed; 1806995e5daSNemanja Ivanovic } 1816995e5daSNemanja Ivanovic }; 1826995e5daSNemanja Ivanovic } 1836995e5daSNemanja Ivanovic 1846995e5daSNemanja Ivanovic INITIALIZE_PASS(PPCPreEmitPeephole, DEBUG_TYPE, "PowerPC Pre-Emit Peephole", 1856995e5daSNemanja Ivanovic false, false) 1866995e5daSNemanja Ivanovic char PPCPreEmitPeephole::ID = 0; 1876995e5daSNemanja Ivanovic 1886995e5daSNemanja Ivanovic FunctionPass *llvm::createPPCPreEmitPeepholePass() { 1896995e5daSNemanja Ivanovic return new PPCPreEmitPeephole(); 1906995e5daSNemanja Ivanovic } 191