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