16995e5daSNemanja Ivanovic //===--------- PPCPreEmitPeephole.cpp - Late peephole optimizations -------===// 26995e5daSNemanja Ivanovic // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler 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" 24a60251d7SStefan Pintilie #include "llvm/MC/MCContext.h" 256995e5daSNemanja Ivanovic #include "llvm/Support/CommandLine.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"); 3882205914Sczhengsz STATISTIC(NumFrameOffFoldInPreEmit, 3982205914Sczhengsz "Number of folding frame offset by using r+r in pre-emit peephole"); 406995e5daSNemanja Ivanovic 416995e5daSNemanja Ivanovic static cl::opt<bool> 4281883ca0SStefan Pintilie EnablePCRelLinkerOpt("ppc-pcrel-linker-opt", cl::Hidden, cl::init(true), 4381883ca0SStefan Pintilie cl::desc("enable PC Relative linker optimization")); 4481883ca0SStefan Pintilie 4581883ca0SStefan Pintilie static cl::opt<bool> 464e1f5e07SNemanja Ivanovic RunPreEmitPeephole("ppc-late-peephole", cl::Hidden, cl::init(true), 476995e5daSNemanja Ivanovic cl::desc("Run pre-emit peephole optimizations.")); 486995e5daSNemanja Ivanovic 496995e5daSNemanja Ivanovic namespace { 50a60251d7SStefan Pintilie 51a60251d7SStefan Pintilie static bool hasPCRelativeForm(MachineInstr &Use) { 52a60251d7SStefan Pintilie switch (Use.getOpcode()) { 53a60251d7SStefan Pintilie default: 54a60251d7SStefan Pintilie return false; 55a60251d7SStefan Pintilie case PPC::LBZ: 56a60251d7SStefan Pintilie case PPC::LBZ8: 57a60251d7SStefan Pintilie case PPC::LHA: 58a60251d7SStefan Pintilie case PPC::LHA8: 59a60251d7SStefan Pintilie case PPC::LHZ: 60a60251d7SStefan Pintilie case PPC::LHZ8: 61a60251d7SStefan Pintilie case PPC::LWZ: 62a60251d7SStefan Pintilie case PPC::LWZ8: 63a60251d7SStefan Pintilie case PPC::STB: 64a60251d7SStefan Pintilie case PPC::STB8: 65a60251d7SStefan Pintilie case PPC::STH: 66a60251d7SStefan Pintilie case PPC::STH8: 67a60251d7SStefan Pintilie case PPC::STW: 68a60251d7SStefan Pintilie case PPC::STW8: 69a60251d7SStefan Pintilie case PPC::LD: 70a60251d7SStefan Pintilie case PPC::STD: 71a60251d7SStefan Pintilie case PPC::LWA: 72a60251d7SStefan Pintilie case PPC::LXSD: 73a60251d7SStefan Pintilie case PPC::LXSSP: 74a60251d7SStefan Pintilie case PPC::LXV: 75a60251d7SStefan Pintilie case PPC::STXSD: 76a60251d7SStefan Pintilie case PPC::STXSSP: 77a60251d7SStefan Pintilie case PPC::STXV: 78a60251d7SStefan Pintilie case PPC::LFD: 79a60251d7SStefan Pintilie case PPC::LFS: 80a60251d7SStefan Pintilie case PPC::STFD: 81a60251d7SStefan Pintilie case PPC::STFS: 82a60251d7SStefan Pintilie case PPC::DFLOADf32: 83a60251d7SStefan Pintilie case PPC::DFLOADf64: 84a60251d7SStefan Pintilie case PPC::DFSTOREf32: 85a60251d7SStefan Pintilie case PPC::DFSTOREf64: 86a60251d7SStefan Pintilie return true; 87a60251d7SStefan Pintilie } 88a60251d7SStefan Pintilie } 89a60251d7SStefan Pintilie 906995e5daSNemanja Ivanovic class PPCPreEmitPeephole : public MachineFunctionPass { 916995e5daSNemanja Ivanovic public: 926995e5daSNemanja Ivanovic static char ID; 936995e5daSNemanja Ivanovic PPCPreEmitPeephole() : MachineFunctionPass(ID) { 946995e5daSNemanja Ivanovic initializePPCPreEmitPeepholePass(*PassRegistry::getPassRegistry()); 956995e5daSNemanja Ivanovic } 966995e5daSNemanja Ivanovic 976995e5daSNemanja Ivanovic void getAnalysisUsage(AnalysisUsage &AU) const override { 986995e5daSNemanja Ivanovic MachineFunctionPass::getAnalysisUsage(AU); 996995e5daSNemanja Ivanovic } 1006995e5daSNemanja Ivanovic 1016995e5daSNemanja Ivanovic MachineFunctionProperties getRequiredProperties() const override { 1026995e5daSNemanja Ivanovic return MachineFunctionProperties().set( 1036995e5daSNemanja Ivanovic MachineFunctionProperties::Property::NoVRegs); 1046995e5daSNemanja Ivanovic } 1056995e5daSNemanja Ivanovic 10641a010a4SYi-Hong Lyu // This function removes any redundant load immediates. It has two level 10741a010a4SYi-Hong Lyu // loops - The outer loop finds the load immediates BBI that could be used 10841a010a4SYi-Hong Lyu // to replace following redundancy. The inner loop scans instructions that 10941a010a4SYi-Hong Lyu // after BBI to find redundancy and update kill/dead flags accordingly. If 11041a010a4SYi-Hong Lyu // AfterBBI is the same as BBI, it is redundant, otherwise any instructions 11141a010a4SYi-Hong Lyu // that modify the def register of BBI would break the scanning. 11241a010a4SYi-Hong Lyu // DeadOrKillToUnset is a pointer to the previous operand that had the 11341a010a4SYi-Hong Lyu // kill/dead flag set. It keeps track of the def register of BBI, the use 11441a010a4SYi-Hong Lyu // registers of AfterBBIs and the def registers of AfterBBIs. 11541a010a4SYi-Hong Lyu bool removeRedundantLIs(MachineBasicBlock &MBB, 11641a010a4SYi-Hong Lyu const TargetRegisterInfo *TRI) { 11741a010a4SYi-Hong Lyu LLVM_DEBUG(dbgs() << "Remove redundant load immediates from MBB:\n"; 11841a010a4SYi-Hong Lyu MBB.dump(); dbgs() << "\n"); 11941a010a4SYi-Hong Lyu 12041a010a4SYi-Hong Lyu DenseSet<MachineInstr *> InstrsToErase; 12141a010a4SYi-Hong Lyu for (auto BBI = MBB.instr_begin(); BBI != MBB.instr_end(); ++BBI) { 12241a010a4SYi-Hong Lyu // Skip load immediate that is marked to be erased later because it 12341a010a4SYi-Hong Lyu // cannot be used to replace any other instructions. 124*56edfcadSKazu Hirata if (InstrsToErase.contains(&*BBI)) 12541a010a4SYi-Hong Lyu continue; 12641a010a4SYi-Hong Lyu // Skip non-load immediate. 12741a010a4SYi-Hong Lyu unsigned Opc = BBI->getOpcode(); 12841a010a4SYi-Hong Lyu if (Opc != PPC::LI && Opc != PPC::LI8 && Opc != PPC::LIS && 12941a010a4SYi-Hong Lyu Opc != PPC::LIS8) 13041a010a4SYi-Hong Lyu continue; 13141a010a4SYi-Hong Lyu // Skip load immediate, where the operand is a relocation (e.g., $r3 = 13241a010a4SYi-Hong Lyu // LI target-flags(ppc-lo) %const.0). 13341a010a4SYi-Hong Lyu if (!BBI->getOperand(1).isImm()) 13441a010a4SYi-Hong Lyu continue; 13541a010a4SYi-Hong Lyu assert(BBI->getOperand(0).isReg() && 13641a010a4SYi-Hong Lyu "Expected a register for the first operand"); 13741a010a4SYi-Hong Lyu 13841a010a4SYi-Hong Lyu LLVM_DEBUG(dbgs() << "Scanning after load immediate: "; BBI->dump();); 13941a010a4SYi-Hong Lyu 1400c476111SDaniel Sanders Register Reg = BBI->getOperand(0).getReg(); 14141a010a4SYi-Hong Lyu int64_t Imm = BBI->getOperand(1).getImm(); 14241a010a4SYi-Hong Lyu MachineOperand *DeadOrKillToUnset = nullptr; 14341a010a4SYi-Hong Lyu if (BBI->getOperand(0).isDead()) { 14441a010a4SYi-Hong Lyu DeadOrKillToUnset = &BBI->getOperand(0); 14541a010a4SYi-Hong Lyu LLVM_DEBUG(dbgs() << " Kill flag of " << *DeadOrKillToUnset 14641a010a4SYi-Hong Lyu << " from load immediate " << *BBI 14741a010a4SYi-Hong Lyu << " is a unsetting candidate\n"); 14841a010a4SYi-Hong Lyu } 14941a010a4SYi-Hong Lyu // This loop scans instructions after BBI to see if there is any 15041a010a4SYi-Hong Lyu // redundant load immediate. 15141a010a4SYi-Hong Lyu for (auto AfterBBI = std::next(BBI); AfterBBI != MBB.instr_end(); 15241a010a4SYi-Hong Lyu ++AfterBBI) { 15341a010a4SYi-Hong Lyu // Track the operand that kill Reg. We would unset the kill flag of 15441a010a4SYi-Hong Lyu // the operand if there is a following redundant load immediate. 15541a010a4SYi-Hong Lyu int KillIdx = AfterBBI->findRegisterUseOperandIdx(Reg, true, TRI); 1567f3787c0SNemanja Ivanovic 1577f3787c0SNemanja Ivanovic // We can't just clear implicit kills, so if we encounter one, stop 1587f3787c0SNemanja Ivanovic // looking further. 1597f3787c0SNemanja Ivanovic if (KillIdx != -1 && AfterBBI->getOperand(KillIdx).isImplicit()) { 1607f3787c0SNemanja Ivanovic LLVM_DEBUG(dbgs() 1617f3787c0SNemanja Ivanovic << "Encountered an implicit kill, cannot proceed: "); 1627f3787c0SNemanja Ivanovic LLVM_DEBUG(AfterBBI->dump()); 1637f3787c0SNemanja Ivanovic break; 1647f3787c0SNemanja Ivanovic } 1657f3787c0SNemanja Ivanovic 16641a010a4SYi-Hong Lyu if (KillIdx != -1) { 16741a010a4SYi-Hong Lyu assert(!DeadOrKillToUnset && "Shouldn't kill same register twice"); 16841a010a4SYi-Hong Lyu DeadOrKillToUnset = &AfterBBI->getOperand(KillIdx); 16941a010a4SYi-Hong Lyu LLVM_DEBUG(dbgs() 17041a010a4SYi-Hong Lyu << " Kill flag of " << *DeadOrKillToUnset << " from " 17141a010a4SYi-Hong Lyu << *AfterBBI << " is a unsetting candidate\n"); 17241a010a4SYi-Hong Lyu } 17341a010a4SYi-Hong Lyu 17441a010a4SYi-Hong Lyu if (!AfterBBI->modifiesRegister(Reg, TRI)) 17541a010a4SYi-Hong Lyu continue; 17641a010a4SYi-Hong Lyu // Finish scanning because Reg is overwritten by a non-load 17741a010a4SYi-Hong Lyu // instruction. 17841a010a4SYi-Hong Lyu if (AfterBBI->getOpcode() != Opc) 17941a010a4SYi-Hong Lyu break; 18041a010a4SYi-Hong Lyu assert(AfterBBI->getOperand(0).isReg() && 18141a010a4SYi-Hong Lyu "Expected a register for the first operand"); 18241a010a4SYi-Hong Lyu // Finish scanning because Reg is overwritten by a relocation or a 18341a010a4SYi-Hong Lyu // different value. 18441a010a4SYi-Hong Lyu if (!AfterBBI->getOperand(1).isImm() || 18541a010a4SYi-Hong Lyu AfterBBI->getOperand(1).getImm() != Imm) 18641a010a4SYi-Hong Lyu break; 18741a010a4SYi-Hong Lyu 18841a010a4SYi-Hong Lyu // It loads same immediate value to the same Reg, which is redundant. 18941a010a4SYi-Hong Lyu // We would unset kill flag in previous Reg usage to extend live range 19041a010a4SYi-Hong Lyu // of Reg first, then remove the redundancy. 1912fbfb04fSYi-Hong Lyu if (DeadOrKillToUnset) { 1922fbfb04fSYi-Hong Lyu LLVM_DEBUG(dbgs() 1932fbfb04fSYi-Hong Lyu << " Unset dead/kill flag of " << *DeadOrKillToUnset 19441a010a4SYi-Hong Lyu << " from " << *DeadOrKillToUnset->getParent()); 19541a010a4SYi-Hong Lyu if (DeadOrKillToUnset->isDef()) 19641a010a4SYi-Hong Lyu DeadOrKillToUnset->setIsDead(false); 19741a010a4SYi-Hong Lyu else 19841a010a4SYi-Hong Lyu DeadOrKillToUnset->setIsKill(false); 1992fbfb04fSYi-Hong Lyu } 20041a010a4SYi-Hong Lyu DeadOrKillToUnset = 20141a010a4SYi-Hong Lyu AfterBBI->findRegisterDefOperand(Reg, true, true, TRI); 20241a010a4SYi-Hong Lyu if (DeadOrKillToUnset) 20341a010a4SYi-Hong Lyu LLVM_DEBUG(dbgs() 20441a010a4SYi-Hong Lyu << " Dead flag of " << *DeadOrKillToUnset << " from " 20541a010a4SYi-Hong Lyu << *AfterBBI << " is a unsetting candidate\n"); 20641a010a4SYi-Hong Lyu InstrsToErase.insert(&*AfterBBI); 20741a010a4SYi-Hong Lyu LLVM_DEBUG(dbgs() << " Remove redundant load immediate: "; 20841a010a4SYi-Hong Lyu AfterBBI->dump()); 20941a010a4SYi-Hong Lyu } 21041a010a4SYi-Hong Lyu } 21141a010a4SYi-Hong Lyu 21241a010a4SYi-Hong Lyu for (MachineInstr *MI : InstrsToErase) { 21341a010a4SYi-Hong Lyu MI->eraseFromParent(); 21441a010a4SYi-Hong Lyu } 21541a010a4SYi-Hong Lyu NumRemovedInPreEmit += InstrsToErase.size(); 21641a010a4SYi-Hong Lyu return !InstrsToErase.empty(); 21741a010a4SYi-Hong Lyu } 21841a010a4SYi-Hong Lyu 219a60251d7SStefan Pintilie // Check if this instruction is a PLDpc that is part of a GOT indirect 220a60251d7SStefan Pintilie // access. 221a60251d7SStefan Pintilie bool isGOTPLDpc(MachineInstr &Instr) { 222a60251d7SStefan Pintilie if (Instr.getOpcode() != PPC::PLDpc) 223a60251d7SStefan Pintilie return false; 224a60251d7SStefan Pintilie 225a60251d7SStefan Pintilie // The result must be a register. 226a60251d7SStefan Pintilie const MachineOperand &LoadedAddressReg = Instr.getOperand(0); 227a60251d7SStefan Pintilie if (!LoadedAddressReg.isReg()) 228a60251d7SStefan Pintilie return false; 229a60251d7SStefan Pintilie 230a60251d7SStefan Pintilie // Make sure that this is a global symbol. 231a60251d7SStefan Pintilie const MachineOperand &SymbolOp = Instr.getOperand(1); 232a60251d7SStefan Pintilie if (!SymbolOp.isGlobal()) 233a60251d7SStefan Pintilie return false; 234a60251d7SStefan Pintilie 235a60251d7SStefan Pintilie // Finally return true only if the GOT flag is present. 236a60251d7SStefan Pintilie return (SymbolOp.getTargetFlags() & PPCII::MO_GOT_FLAG); 237a60251d7SStefan Pintilie } 238a60251d7SStefan Pintilie 239a60251d7SStefan Pintilie bool addLinkerOpt(MachineBasicBlock &MBB, const TargetRegisterInfo *TRI) { 240a60251d7SStefan Pintilie MachineFunction *MF = MBB.getParent(); 24181883ca0SStefan Pintilie // If the linker opt is disabled then just return. 24281883ca0SStefan Pintilie if (!EnablePCRelLinkerOpt) 24381883ca0SStefan Pintilie return false; 24481883ca0SStefan Pintilie 245a60251d7SStefan Pintilie // Add this linker opt only if we are using PC Relative memops. 246a60251d7SStefan Pintilie if (!MF->getSubtarget<PPCSubtarget>().isUsingPCRelativeCalls()) 247a60251d7SStefan Pintilie return false; 248a60251d7SStefan Pintilie 249a60251d7SStefan Pintilie // Struct to keep track of one def/use pair for a GOT indirect access. 250a60251d7SStefan Pintilie struct GOTDefUsePair { 251a60251d7SStefan Pintilie MachineBasicBlock::iterator DefInst; 252a60251d7SStefan Pintilie MachineBasicBlock::iterator UseInst; 253a60251d7SStefan Pintilie Register DefReg; 254a60251d7SStefan Pintilie Register UseReg; 255a60251d7SStefan Pintilie bool StillValid; 256a60251d7SStefan Pintilie }; 257a60251d7SStefan Pintilie // Vector of def/ues pairs in this basic block. 258a60251d7SStefan Pintilie SmallVector<GOTDefUsePair, 4> CandPairs; 259a60251d7SStefan Pintilie SmallVector<GOTDefUsePair, 4> ValidPairs; 260a60251d7SStefan Pintilie bool MadeChange = false; 261a60251d7SStefan Pintilie 262a60251d7SStefan Pintilie // Run through all of the instructions in the basic block and try to 263a60251d7SStefan Pintilie // collect potential pairs of GOT indirect access instructions. 264a60251d7SStefan Pintilie for (auto BBI = MBB.instr_begin(); BBI != MBB.instr_end(); ++BBI) { 265a60251d7SStefan Pintilie // Look for the initial GOT indirect load. 266a60251d7SStefan Pintilie if (isGOTPLDpc(*BBI)) { 267a60251d7SStefan Pintilie GOTDefUsePair CurrentPair{BBI, MachineBasicBlock::iterator(), 268a60251d7SStefan Pintilie BBI->getOperand(0).getReg(), 269a60251d7SStefan Pintilie PPC::NoRegister, true}; 270a60251d7SStefan Pintilie CandPairs.push_back(CurrentPair); 271a60251d7SStefan Pintilie continue; 272a60251d7SStefan Pintilie } 273a60251d7SStefan Pintilie 274a60251d7SStefan Pintilie // We haven't encountered any new PLD instructions, nothing to check. 275a60251d7SStefan Pintilie if (CandPairs.empty()) 276a60251d7SStefan Pintilie continue; 277a60251d7SStefan Pintilie 278a60251d7SStefan Pintilie // Run through the candidate pairs and see if any of the registers 279a60251d7SStefan Pintilie // defined in the PLD instructions are used by this instruction. 280a60251d7SStefan Pintilie // Note: the size of CandPairs can change in the loop. 281a60251d7SStefan Pintilie for (unsigned Idx = 0; Idx < CandPairs.size(); Idx++) { 282a60251d7SStefan Pintilie GOTDefUsePair &Pair = CandPairs[Idx]; 283a60251d7SStefan Pintilie // The instruction does not use or modify this PLD's def reg, 284a60251d7SStefan Pintilie // ignore it. 285a60251d7SStefan Pintilie if (!BBI->readsRegister(Pair.DefReg, TRI) && 286a60251d7SStefan Pintilie !BBI->modifiesRegister(Pair.DefReg, TRI)) 287a60251d7SStefan Pintilie continue; 288a60251d7SStefan Pintilie 289a60251d7SStefan Pintilie // The use needs to be used in the address compuation and not 290a60251d7SStefan Pintilie // as the register being stored for a store. 291a60251d7SStefan Pintilie const MachineOperand *UseOp = 292a60251d7SStefan Pintilie hasPCRelativeForm(*BBI) ? &BBI->getOperand(2) : nullptr; 293a60251d7SStefan Pintilie 294a60251d7SStefan Pintilie // Check for a valid use. 295a60251d7SStefan Pintilie if (UseOp && UseOp->isReg() && UseOp->getReg() == Pair.DefReg && 296a60251d7SStefan Pintilie UseOp->isUse() && UseOp->isKill()) { 297a60251d7SStefan Pintilie Pair.UseInst = BBI; 298a60251d7SStefan Pintilie Pair.UseReg = BBI->getOperand(0).getReg(); 299a60251d7SStefan Pintilie ValidPairs.push_back(Pair); 300a60251d7SStefan Pintilie } 301a60251d7SStefan Pintilie CandPairs.erase(CandPairs.begin() + Idx); 302a60251d7SStefan Pintilie } 303a60251d7SStefan Pintilie } 304a60251d7SStefan Pintilie 305a60251d7SStefan Pintilie // Go through all of the pairs and check for any more valid uses. 306a60251d7SStefan Pintilie for (auto Pair = ValidPairs.begin(); Pair != ValidPairs.end(); Pair++) { 307a60251d7SStefan Pintilie // We shouldn't be here if we don't have a valid pair. 308a60251d7SStefan Pintilie assert(Pair->UseInst.isValid() && Pair->StillValid && 309a60251d7SStefan Pintilie "Kept an invalid def/use pair for GOT PCRel opt"); 310a60251d7SStefan Pintilie // We have found a potential pair. Search through the instructions 311a60251d7SStefan Pintilie // between the def and the use to see if it is valid to mark this as a 312a60251d7SStefan Pintilie // linker opt. 313a60251d7SStefan Pintilie MachineBasicBlock::iterator BBI = Pair->DefInst; 314a60251d7SStefan Pintilie ++BBI; 315a60251d7SStefan Pintilie for (; BBI != Pair->UseInst; ++BBI) { 316a60251d7SStefan Pintilie if (BBI->readsRegister(Pair->UseReg, TRI) || 317a60251d7SStefan Pintilie BBI->modifiesRegister(Pair->UseReg, TRI)) { 318a60251d7SStefan Pintilie Pair->StillValid = false; 319a60251d7SStefan Pintilie break; 320a60251d7SStefan Pintilie } 321a60251d7SStefan Pintilie } 322a60251d7SStefan Pintilie 323a60251d7SStefan Pintilie if (!Pair->StillValid) 324a60251d7SStefan Pintilie continue; 325a60251d7SStefan Pintilie 326a60251d7SStefan Pintilie // The load/store instruction that uses the address from the PLD will 327a60251d7SStefan Pintilie // either use a register (for a store) or define a register (for the 328a60251d7SStefan Pintilie // load). That register will be added as an implicit def to the PLD 329a60251d7SStefan Pintilie // and as an implicit use on the second memory op. This is a precaution 330a60251d7SStefan Pintilie // to prevent future passes from using that register between the two 331a60251d7SStefan Pintilie // instructions. 332a60251d7SStefan Pintilie MachineOperand ImplDef = 333a60251d7SStefan Pintilie MachineOperand::CreateReg(Pair->UseReg, true, true); 334a60251d7SStefan Pintilie MachineOperand ImplUse = 335a60251d7SStefan Pintilie MachineOperand::CreateReg(Pair->UseReg, false, true); 336a60251d7SStefan Pintilie Pair->DefInst->addOperand(ImplDef); 337a60251d7SStefan Pintilie Pair->UseInst->addOperand(ImplUse); 338a60251d7SStefan Pintilie 339a60251d7SStefan Pintilie // Create the symbol. 340a60251d7SStefan Pintilie MCContext &Context = MF->getContext(); 341a60251d7SStefan Pintilie MCSymbol *Symbol = 342a60251d7SStefan Pintilie Context.createTempSymbol(Twine("pcrel"), false, false); 343a60251d7SStefan Pintilie MachineOperand PCRelLabel = 344a60251d7SStefan Pintilie MachineOperand::CreateMCSymbol(Symbol, PPCII::MO_PCREL_OPT_FLAG); 345a60251d7SStefan Pintilie Pair->DefInst->addOperand(*MF, PCRelLabel); 346a60251d7SStefan Pintilie Pair->UseInst->addOperand(*MF, PCRelLabel); 347a60251d7SStefan Pintilie MadeChange |= true; 348a60251d7SStefan Pintilie } 349a60251d7SStefan Pintilie return MadeChange; 350a60251d7SStefan Pintilie } 351a60251d7SStefan Pintilie 35218db29eaSBaptiste Saleil // This function removes redundant pairs of accumulator prime/unprime 35318db29eaSBaptiste Saleil // instructions. In some situations, it's possible the compiler inserts an 35418db29eaSBaptiste Saleil // accumulator prime instruction followed by an unprime instruction (e.g. 35518db29eaSBaptiste Saleil // when we store an accumulator after restoring it from a spill). If the 35618db29eaSBaptiste Saleil // accumulator is not used between the two, they can be removed. This 35718db29eaSBaptiste Saleil // function removes these redundant pairs from basic blocks. 35818db29eaSBaptiste Saleil // The algorithm is quite straightforward - every time we encounter a prime 35918db29eaSBaptiste Saleil // instruction, the primed register is added to a candidate set. Any use 36018db29eaSBaptiste Saleil // other than a prime removes the candidate from the set and any de-prime 36118db29eaSBaptiste Saleil // of a current candidate marks both the prime and de-prime for removal. 36218db29eaSBaptiste Saleil // This way we ensure we only remove prime/de-prime *pairs* with no 36318db29eaSBaptiste Saleil // intervening uses. 36418db29eaSBaptiste Saleil bool removeAccPrimeUnprime(MachineBasicBlock &MBB) { 36518db29eaSBaptiste Saleil DenseSet<MachineInstr *> InstrsToErase; 36618db29eaSBaptiste Saleil // Initially, none of the acc registers are candidates. 36718db29eaSBaptiste Saleil SmallVector<MachineInstr *, 8> Candidates( 36818db29eaSBaptiste Saleil PPC::UACCRCRegClass.getNumRegs(), nullptr); 36918db29eaSBaptiste Saleil 37018db29eaSBaptiste Saleil for (MachineInstr &BBI : MBB.instrs()) { 37118db29eaSBaptiste Saleil unsigned Opc = BBI.getOpcode(); 37218db29eaSBaptiste Saleil // If we are visiting a xxmtacc instruction, we add it and its operand 37318db29eaSBaptiste Saleil // register to the candidate set. 37418db29eaSBaptiste Saleil if (Opc == PPC::XXMTACC) { 37518db29eaSBaptiste Saleil Register Acc = BBI.getOperand(0).getReg(); 37618db29eaSBaptiste Saleil assert(PPC::ACCRCRegClass.contains(Acc) && 37718db29eaSBaptiste Saleil "Unexpected register for XXMTACC"); 37818db29eaSBaptiste Saleil Candidates[Acc - PPC::ACC0] = &BBI; 37918db29eaSBaptiste Saleil } 38018db29eaSBaptiste Saleil // If we are visiting a xxmfacc instruction and its operand register is 38118db29eaSBaptiste Saleil // in the candidate set, we mark the two instructions for removal. 38218db29eaSBaptiste Saleil else if (Opc == PPC::XXMFACC) { 38318db29eaSBaptiste Saleil Register Acc = BBI.getOperand(0).getReg(); 38418db29eaSBaptiste Saleil assert(PPC::ACCRCRegClass.contains(Acc) && 38518db29eaSBaptiste Saleil "Unexpected register for XXMFACC"); 38618db29eaSBaptiste Saleil if (!Candidates[Acc - PPC::ACC0]) 38718db29eaSBaptiste Saleil continue; 38818db29eaSBaptiste Saleil InstrsToErase.insert(&BBI); 38918db29eaSBaptiste Saleil InstrsToErase.insert(Candidates[Acc - PPC::ACC0]); 39018db29eaSBaptiste Saleil } 39118db29eaSBaptiste Saleil // If we are visiting an instruction using an accumulator register 39218db29eaSBaptiste Saleil // as operand, we remove it from the candidate set. 39318db29eaSBaptiste Saleil else { 39418db29eaSBaptiste Saleil for (MachineOperand &Operand : BBI.operands()) { 39518db29eaSBaptiste Saleil if (!Operand.isReg()) 39618db29eaSBaptiste Saleil continue; 39718db29eaSBaptiste Saleil Register Reg = Operand.getReg(); 39818db29eaSBaptiste Saleil if (PPC::ACCRCRegClass.contains(Reg)) 39918db29eaSBaptiste Saleil Candidates[Reg - PPC::ACC0] = nullptr; 40018db29eaSBaptiste Saleil } 40118db29eaSBaptiste Saleil } 40218db29eaSBaptiste Saleil } 40318db29eaSBaptiste Saleil 40418db29eaSBaptiste Saleil for (MachineInstr *MI : InstrsToErase) 40518db29eaSBaptiste Saleil MI->eraseFromParent(); 40618db29eaSBaptiste Saleil NumRemovedInPreEmit += InstrsToErase.size(); 40718db29eaSBaptiste Saleil return !InstrsToErase.empty(); 40818db29eaSBaptiste Saleil } 40918db29eaSBaptiste Saleil 4106995e5daSNemanja Ivanovic bool runOnMachineFunction(MachineFunction &MF) override { 411a3db9c08SYi-Hong Lyu if (skipFunction(MF.getFunction()) || !RunPreEmitPeephole) { 412a3db9c08SYi-Hong Lyu // Remove UNENCODED_NOP even when this pass is disabled. 413a3db9c08SYi-Hong Lyu // This needs to be done unconditionally so we don't emit zeros 414a3db9c08SYi-Hong Lyu // in the instruction stream. 415a3db9c08SYi-Hong Lyu SmallVector<MachineInstr *, 4> InstrsToErase; 416a3db9c08SYi-Hong Lyu for (MachineBasicBlock &MBB : MF) 417a3db9c08SYi-Hong Lyu for (MachineInstr &MI : MBB) 418a3db9c08SYi-Hong Lyu if (MI.getOpcode() == PPC::UNENCODED_NOP) 419a3db9c08SYi-Hong Lyu InstrsToErase.push_back(&MI); 420a3db9c08SYi-Hong Lyu for (MachineInstr *MI : InstrsToErase) 421a3db9c08SYi-Hong Lyu MI->eraseFromParent(); 4226995e5daSNemanja Ivanovic return false; 423a3db9c08SYi-Hong Lyu } 4246995e5daSNemanja Ivanovic bool Changed = false; 4256995e5daSNemanja Ivanovic const PPCInstrInfo *TII = MF.getSubtarget<PPCSubtarget>().getInstrInfo(); 42620982f09SHiroshi Inoue const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 4276995e5daSNemanja Ivanovic SmallVector<MachineInstr *, 4> InstrsToErase; 4286995e5daSNemanja Ivanovic for (MachineBasicBlock &MBB : MF) { 42941a010a4SYi-Hong Lyu Changed |= removeRedundantLIs(MBB, TRI); 430a60251d7SStefan Pintilie Changed |= addLinkerOpt(MBB, TRI); 43118db29eaSBaptiste Saleil Changed |= removeAccPrimeUnprime(MBB); 4326995e5daSNemanja Ivanovic for (MachineInstr &MI : MBB) { 4334c0b110eSNemanja Ivanovic unsigned Opc = MI.getOpcode(); 434a3db9c08SYi-Hong Lyu if (Opc == PPC::UNENCODED_NOP) { 435a3db9c08SYi-Hong Lyu InstrsToErase.push_back(&MI); 436a3db9c08SYi-Hong Lyu continue; 437a3db9c08SYi-Hong Lyu } 4384c0b110eSNemanja Ivanovic // Detect self copies - these can result from running AADB. 4394c0b110eSNemanja Ivanovic if (PPCInstrInfo::isSameClassPhysRegCopy(Opc)) { 4404c0b110eSNemanja Ivanovic const MCInstrDesc &MCID = TII->get(Opc); 4414c0b110eSNemanja Ivanovic if (MCID.getNumOperands() == 3 && 4424c0b110eSNemanja Ivanovic MI.getOperand(0).getReg() == MI.getOperand(1).getReg() && 4434c0b110eSNemanja Ivanovic MI.getOperand(0).getReg() == MI.getOperand(2).getReg()) { 4444c0b110eSNemanja Ivanovic NumberOfSelfCopies++; 4454c0b110eSNemanja Ivanovic LLVM_DEBUG(dbgs() << "Deleting self-copy instruction: "); 4464c0b110eSNemanja Ivanovic LLVM_DEBUG(MI.dump()); 4474c0b110eSNemanja Ivanovic InstrsToErase.push_back(&MI); 4484c0b110eSNemanja Ivanovic continue; 4494c0b110eSNemanja Ivanovic } 4504c0b110eSNemanja Ivanovic else if (MCID.getNumOperands() == 2 && 4514c0b110eSNemanja Ivanovic MI.getOperand(0).getReg() == MI.getOperand(1).getReg()) { 4524c0b110eSNemanja Ivanovic NumberOfSelfCopies++; 4534c0b110eSNemanja Ivanovic LLVM_DEBUG(dbgs() << "Deleting self-copy instruction: "); 4544c0b110eSNemanja Ivanovic LLVM_DEBUG(MI.dump()); 4554c0b110eSNemanja Ivanovic InstrsToErase.push_back(&MI); 4564c0b110eSNemanja Ivanovic continue; 4574c0b110eSNemanja Ivanovic } 4584c0b110eSNemanja Ivanovic } 4596995e5daSNemanja Ivanovic MachineInstr *DefMIToErase = nullptr; 4606995e5daSNemanja Ivanovic if (TII->convertToImmediateForm(MI, &DefMIToErase)) { 4616995e5daSNemanja Ivanovic Changed = true; 4626995e5daSNemanja Ivanovic NumRRConvertedInPreEmit++; 463d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Converted instruction to imm form: "); 464d34e60caSNicola Zaghen LLVM_DEBUG(MI.dump()); 4656995e5daSNemanja Ivanovic if (DefMIToErase) { 4666995e5daSNemanja Ivanovic InstrsToErase.push_back(DefMIToErase); 4676995e5daSNemanja Ivanovic } 4686995e5daSNemanja Ivanovic } 46982205914Sczhengsz if (TII->foldFrameOffset(MI)) { 47082205914Sczhengsz Changed = true; 47182205914Sczhengsz NumFrameOffFoldInPreEmit++; 47282205914Sczhengsz LLVM_DEBUG(dbgs() << "Frame offset folding by using index form: "); 47382205914Sczhengsz LLVM_DEBUG(MI.dump()); 47482205914Sczhengsz } 4756995e5daSNemanja Ivanovic } 47620982f09SHiroshi Inoue 47720982f09SHiroshi Inoue // Eliminate conditional branch based on a constant CR bit by 47820982f09SHiroshi Inoue // CRSET or CRUNSET. We eliminate the conditional branch or 47920982f09SHiroshi Inoue // convert it into an unconditional branch. Also, if the CR bit 48020982f09SHiroshi Inoue // is not used by other instructions, we eliminate CRSET as well. 48120982f09SHiroshi Inoue auto I = MBB.getFirstInstrTerminator(); 48220982f09SHiroshi Inoue if (I == MBB.instr_end()) 48320982f09SHiroshi Inoue continue; 48420982f09SHiroshi Inoue MachineInstr *Br = &*I; 48520982f09SHiroshi Inoue if (Br->getOpcode() != PPC::BC && Br->getOpcode() != PPC::BCn) 48620982f09SHiroshi Inoue continue; 48720982f09SHiroshi Inoue MachineInstr *CRSetMI = nullptr; 4880c476111SDaniel Sanders Register CRBit = Br->getOperand(0).getReg(); 48920982f09SHiroshi Inoue unsigned CRReg = getCRFromCRBit(CRBit); 49020982f09SHiroshi Inoue bool SeenUse = false; 49120982f09SHiroshi Inoue MachineBasicBlock::reverse_iterator It = Br, Er = MBB.rend(); 49220982f09SHiroshi Inoue for (It++; It != Er; It++) { 49320982f09SHiroshi Inoue if (It->modifiesRegister(CRBit, TRI)) { 49420982f09SHiroshi Inoue if ((It->getOpcode() == PPC::CRUNSET || 49520982f09SHiroshi Inoue It->getOpcode() == PPC::CRSET) && 49620982f09SHiroshi Inoue It->getOperand(0).getReg() == CRBit) 49720982f09SHiroshi Inoue CRSetMI = &*It; 49820982f09SHiroshi Inoue break; 49920982f09SHiroshi Inoue } 50020982f09SHiroshi Inoue if (It->readsRegister(CRBit, TRI)) 50120982f09SHiroshi Inoue SeenUse = true; 50220982f09SHiroshi Inoue } 50320982f09SHiroshi Inoue if (!CRSetMI) continue; 50420982f09SHiroshi Inoue 50520982f09SHiroshi Inoue unsigned CRSetOp = CRSetMI->getOpcode(); 50620982f09SHiroshi Inoue if ((Br->getOpcode() == PPC::BCn && CRSetOp == PPC::CRSET) || 50720982f09SHiroshi Inoue (Br->getOpcode() == PPC::BC && CRSetOp == PPC::CRUNSET)) { 50820982f09SHiroshi Inoue // Remove this branch since it cannot be taken. 50920982f09SHiroshi Inoue InstrsToErase.push_back(Br); 51020982f09SHiroshi Inoue MBB.removeSuccessor(Br->getOperand(1).getMBB()); 51120982f09SHiroshi Inoue } 51220982f09SHiroshi Inoue else { 51320982f09SHiroshi Inoue // This conditional branch is always taken. So, remove all branches 51420982f09SHiroshi Inoue // and insert an unconditional branch to the destination of this. 51520982f09SHiroshi Inoue MachineBasicBlock::iterator It = Br, Er = MBB.end(); 516ecc89b76SWei Mi for (; It != Er; It++) { 51720982f09SHiroshi Inoue if (It->isDebugInstr()) continue; 51820982f09SHiroshi Inoue assert(It->isTerminator() && "Non-terminator after a terminator"); 51920982f09SHiroshi Inoue InstrsToErase.push_back(&*It); 52020982f09SHiroshi Inoue } 52120982f09SHiroshi Inoue if (!MBB.isLayoutSuccessor(Br->getOperand(1).getMBB())) { 52220982f09SHiroshi Inoue ArrayRef<MachineOperand> NoCond; 52320982f09SHiroshi Inoue TII->insertBranch(MBB, Br->getOperand(1).getMBB(), nullptr, 52420982f09SHiroshi Inoue NoCond, Br->getDebugLoc()); 52520982f09SHiroshi Inoue } 52620982f09SHiroshi Inoue for (auto &Succ : MBB.successors()) 52720982f09SHiroshi Inoue if (Succ != Br->getOperand(1).getMBB()) { 52820982f09SHiroshi Inoue MBB.removeSuccessor(Succ); 52920982f09SHiroshi Inoue break; 53020982f09SHiroshi Inoue } 53120982f09SHiroshi Inoue } 53220982f09SHiroshi Inoue 53320982f09SHiroshi Inoue // If the CRBit is not used by another instruction, we can eliminate 53420982f09SHiroshi Inoue // CRSET/CRUNSET instruction. 53520982f09SHiroshi Inoue if (!SeenUse) { 53620982f09SHiroshi Inoue // We need to check use of the CRBit in successors. 53720982f09SHiroshi Inoue for (auto &SuccMBB : MBB.successors()) 53820982f09SHiroshi Inoue if (SuccMBB->isLiveIn(CRBit) || SuccMBB->isLiveIn(CRReg)) { 53920982f09SHiroshi Inoue SeenUse = true; 54020982f09SHiroshi Inoue break; 54120982f09SHiroshi Inoue } 54220982f09SHiroshi Inoue if (!SeenUse) 54320982f09SHiroshi Inoue InstrsToErase.push_back(CRSetMI); 54420982f09SHiroshi Inoue } 5456995e5daSNemanja Ivanovic } 5466995e5daSNemanja Ivanovic for (MachineInstr *MI : InstrsToErase) { 547d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "PPC pre-emit peephole: erasing instruction: "); 548d34e60caSNicola Zaghen LLVM_DEBUG(MI->dump()); 5496995e5daSNemanja Ivanovic MI->eraseFromParent(); 5506995e5daSNemanja Ivanovic NumRemovedInPreEmit++; 5516995e5daSNemanja Ivanovic } 5526995e5daSNemanja Ivanovic return Changed; 5536995e5daSNemanja Ivanovic } 5546995e5daSNemanja Ivanovic }; 5556995e5daSNemanja Ivanovic } 5566995e5daSNemanja Ivanovic 5576995e5daSNemanja Ivanovic INITIALIZE_PASS(PPCPreEmitPeephole, DEBUG_TYPE, "PowerPC Pre-Emit Peephole", 5586995e5daSNemanja Ivanovic false, false) 5596995e5daSNemanja Ivanovic char PPCPreEmitPeephole::ID = 0; 5606995e5daSNemanja Ivanovic 5616995e5daSNemanja Ivanovic FunctionPass *llvm::createPPCPreEmitPeepholePass() { 5626995e5daSNemanja Ivanovic return new PPCPreEmitPeephole(); 5636995e5daSNemanja Ivanovic } 564