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> 42*81883ca0SStefan Pintilie EnablePCRelLinkerOpt("ppc-pcrel-linker-opt", cl::Hidden, cl::init(true), 43*81883ca0SStefan Pintilie cl::desc("enable PC Relative linker optimization")); 44*81883ca0SStefan Pintilie 45*81883ca0SStefan 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. 12441a010a4SYi-Hong Lyu if (InstrsToErase.find(&*BBI) != InstrsToErase.end()) 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(); 241*81883ca0SStefan Pintilie // If the linker opt is disabled then just return. 242*81883ca0SStefan Pintilie if (!EnablePCRelLinkerOpt) 243*81883ca0SStefan Pintilie return false; 244*81883ca0SStefan 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 3526995e5daSNemanja Ivanovic bool runOnMachineFunction(MachineFunction &MF) override { 353a3db9c08SYi-Hong Lyu if (skipFunction(MF.getFunction()) || !RunPreEmitPeephole) { 354a3db9c08SYi-Hong Lyu // Remove UNENCODED_NOP even when this pass is disabled. 355a3db9c08SYi-Hong Lyu // This needs to be done unconditionally so we don't emit zeros 356a3db9c08SYi-Hong Lyu // in the instruction stream. 357a3db9c08SYi-Hong Lyu SmallVector<MachineInstr *, 4> InstrsToErase; 358a3db9c08SYi-Hong Lyu for (MachineBasicBlock &MBB : MF) 359a3db9c08SYi-Hong Lyu for (MachineInstr &MI : MBB) 360a3db9c08SYi-Hong Lyu if (MI.getOpcode() == PPC::UNENCODED_NOP) 361a3db9c08SYi-Hong Lyu InstrsToErase.push_back(&MI); 362a3db9c08SYi-Hong Lyu for (MachineInstr *MI : InstrsToErase) 363a3db9c08SYi-Hong Lyu MI->eraseFromParent(); 3646995e5daSNemanja Ivanovic return false; 365a3db9c08SYi-Hong Lyu } 3666995e5daSNemanja Ivanovic bool Changed = false; 3676995e5daSNemanja Ivanovic const PPCInstrInfo *TII = MF.getSubtarget<PPCSubtarget>().getInstrInfo(); 36820982f09SHiroshi Inoue const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 3696995e5daSNemanja Ivanovic SmallVector<MachineInstr *, 4> InstrsToErase; 3706995e5daSNemanja Ivanovic for (MachineBasicBlock &MBB : MF) { 37141a010a4SYi-Hong Lyu Changed |= removeRedundantLIs(MBB, TRI); 372a60251d7SStefan Pintilie Changed |= addLinkerOpt(MBB, TRI); 3736995e5daSNemanja Ivanovic for (MachineInstr &MI : MBB) { 3744c0b110eSNemanja Ivanovic unsigned Opc = MI.getOpcode(); 375a3db9c08SYi-Hong Lyu if (Opc == PPC::UNENCODED_NOP) { 376a3db9c08SYi-Hong Lyu InstrsToErase.push_back(&MI); 377a3db9c08SYi-Hong Lyu continue; 378a3db9c08SYi-Hong Lyu } 3794c0b110eSNemanja Ivanovic // Detect self copies - these can result from running AADB. 3804c0b110eSNemanja Ivanovic if (PPCInstrInfo::isSameClassPhysRegCopy(Opc)) { 3814c0b110eSNemanja Ivanovic const MCInstrDesc &MCID = TII->get(Opc); 3824c0b110eSNemanja Ivanovic if (MCID.getNumOperands() == 3 && 3834c0b110eSNemanja Ivanovic MI.getOperand(0).getReg() == MI.getOperand(1).getReg() && 3844c0b110eSNemanja Ivanovic MI.getOperand(0).getReg() == MI.getOperand(2).getReg()) { 3854c0b110eSNemanja Ivanovic NumberOfSelfCopies++; 3864c0b110eSNemanja Ivanovic LLVM_DEBUG(dbgs() << "Deleting self-copy instruction: "); 3874c0b110eSNemanja Ivanovic LLVM_DEBUG(MI.dump()); 3884c0b110eSNemanja Ivanovic InstrsToErase.push_back(&MI); 3894c0b110eSNemanja Ivanovic continue; 3904c0b110eSNemanja Ivanovic } 3914c0b110eSNemanja Ivanovic else if (MCID.getNumOperands() == 2 && 3924c0b110eSNemanja Ivanovic MI.getOperand(0).getReg() == MI.getOperand(1).getReg()) { 3934c0b110eSNemanja Ivanovic NumberOfSelfCopies++; 3944c0b110eSNemanja Ivanovic LLVM_DEBUG(dbgs() << "Deleting self-copy instruction: "); 3954c0b110eSNemanja Ivanovic LLVM_DEBUG(MI.dump()); 3964c0b110eSNemanja Ivanovic InstrsToErase.push_back(&MI); 3974c0b110eSNemanja Ivanovic continue; 3984c0b110eSNemanja Ivanovic } 3994c0b110eSNemanja Ivanovic } 4006995e5daSNemanja Ivanovic MachineInstr *DefMIToErase = nullptr; 4016995e5daSNemanja Ivanovic if (TII->convertToImmediateForm(MI, &DefMIToErase)) { 4026995e5daSNemanja Ivanovic Changed = true; 4036995e5daSNemanja Ivanovic NumRRConvertedInPreEmit++; 404d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Converted instruction to imm form: "); 405d34e60caSNicola Zaghen LLVM_DEBUG(MI.dump()); 4066995e5daSNemanja Ivanovic if (DefMIToErase) { 4076995e5daSNemanja Ivanovic InstrsToErase.push_back(DefMIToErase); 4086995e5daSNemanja Ivanovic } 4096995e5daSNemanja Ivanovic } 41082205914Sczhengsz if (TII->foldFrameOffset(MI)) { 41182205914Sczhengsz Changed = true; 41282205914Sczhengsz NumFrameOffFoldInPreEmit++; 41382205914Sczhengsz LLVM_DEBUG(dbgs() << "Frame offset folding by using index form: "); 41482205914Sczhengsz LLVM_DEBUG(MI.dump()); 41582205914Sczhengsz } 4166995e5daSNemanja Ivanovic } 41720982f09SHiroshi Inoue 41820982f09SHiroshi Inoue // Eliminate conditional branch based on a constant CR bit by 41920982f09SHiroshi Inoue // CRSET or CRUNSET. We eliminate the conditional branch or 42020982f09SHiroshi Inoue // convert it into an unconditional branch. Also, if the CR bit 42120982f09SHiroshi Inoue // is not used by other instructions, we eliminate CRSET as well. 42220982f09SHiroshi Inoue auto I = MBB.getFirstInstrTerminator(); 42320982f09SHiroshi Inoue if (I == MBB.instr_end()) 42420982f09SHiroshi Inoue continue; 42520982f09SHiroshi Inoue MachineInstr *Br = &*I; 42620982f09SHiroshi Inoue if (Br->getOpcode() != PPC::BC && Br->getOpcode() != PPC::BCn) 42720982f09SHiroshi Inoue continue; 42820982f09SHiroshi Inoue MachineInstr *CRSetMI = nullptr; 4290c476111SDaniel Sanders Register CRBit = Br->getOperand(0).getReg(); 43020982f09SHiroshi Inoue unsigned CRReg = getCRFromCRBit(CRBit); 43120982f09SHiroshi Inoue bool SeenUse = false; 43220982f09SHiroshi Inoue MachineBasicBlock::reverse_iterator It = Br, Er = MBB.rend(); 43320982f09SHiroshi Inoue for (It++; It != Er; It++) { 43420982f09SHiroshi Inoue if (It->modifiesRegister(CRBit, TRI)) { 43520982f09SHiroshi Inoue if ((It->getOpcode() == PPC::CRUNSET || 43620982f09SHiroshi Inoue It->getOpcode() == PPC::CRSET) && 43720982f09SHiroshi Inoue It->getOperand(0).getReg() == CRBit) 43820982f09SHiroshi Inoue CRSetMI = &*It; 43920982f09SHiroshi Inoue break; 44020982f09SHiroshi Inoue } 44120982f09SHiroshi Inoue if (It->readsRegister(CRBit, TRI)) 44220982f09SHiroshi Inoue SeenUse = true; 44320982f09SHiroshi Inoue } 44420982f09SHiroshi Inoue if (!CRSetMI) continue; 44520982f09SHiroshi Inoue 44620982f09SHiroshi Inoue unsigned CRSetOp = CRSetMI->getOpcode(); 44720982f09SHiroshi Inoue if ((Br->getOpcode() == PPC::BCn && CRSetOp == PPC::CRSET) || 44820982f09SHiroshi Inoue (Br->getOpcode() == PPC::BC && CRSetOp == PPC::CRUNSET)) { 44920982f09SHiroshi Inoue // Remove this branch since it cannot be taken. 45020982f09SHiroshi Inoue InstrsToErase.push_back(Br); 45120982f09SHiroshi Inoue MBB.removeSuccessor(Br->getOperand(1).getMBB()); 45220982f09SHiroshi Inoue } 45320982f09SHiroshi Inoue else { 45420982f09SHiroshi Inoue // This conditional branch is always taken. So, remove all branches 45520982f09SHiroshi Inoue // and insert an unconditional branch to the destination of this. 45620982f09SHiroshi Inoue MachineBasicBlock::iterator It = Br, Er = MBB.end(); 457ecc89b76SWei Mi for (; It != Er; It++) { 45820982f09SHiroshi Inoue if (It->isDebugInstr()) continue; 45920982f09SHiroshi Inoue assert(It->isTerminator() && "Non-terminator after a terminator"); 46020982f09SHiroshi Inoue InstrsToErase.push_back(&*It); 46120982f09SHiroshi Inoue } 46220982f09SHiroshi Inoue if (!MBB.isLayoutSuccessor(Br->getOperand(1).getMBB())) { 46320982f09SHiroshi Inoue ArrayRef<MachineOperand> NoCond; 46420982f09SHiroshi Inoue TII->insertBranch(MBB, Br->getOperand(1).getMBB(), nullptr, 46520982f09SHiroshi Inoue NoCond, Br->getDebugLoc()); 46620982f09SHiroshi Inoue } 46720982f09SHiroshi Inoue for (auto &Succ : MBB.successors()) 46820982f09SHiroshi Inoue if (Succ != Br->getOperand(1).getMBB()) { 46920982f09SHiroshi Inoue MBB.removeSuccessor(Succ); 47020982f09SHiroshi Inoue break; 47120982f09SHiroshi Inoue } 47220982f09SHiroshi Inoue } 47320982f09SHiroshi Inoue 47420982f09SHiroshi Inoue // If the CRBit is not used by another instruction, we can eliminate 47520982f09SHiroshi Inoue // CRSET/CRUNSET instruction. 47620982f09SHiroshi Inoue if (!SeenUse) { 47720982f09SHiroshi Inoue // We need to check use of the CRBit in successors. 47820982f09SHiroshi Inoue for (auto &SuccMBB : MBB.successors()) 47920982f09SHiroshi Inoue if (SuccMBB->isLiveIn(CRBit) || SuccMBB->isLiveIn(CRReg)) { 48020982f09SHiroshi Inoue SeenUse = true; 48120982f09SHiroshi Inoue break; 48220982f09SHiroshi Inoue } 48320982f09SHiroshi Inoue if (!SeenUse) 48420982f09SHiroshi Inoue InstrsToErase.push_back(CRSetMI); 48520982f09SHiroshi Inoue } 4866995e5daSNemanja Ivanovic } 4876995e5daSNemanja Ivanovic for (MachineInstr *MI : InstrsToErase) { 488d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "PPC pre-emit peephole: erasing instruction: "); 489d34e60caSNicola Zaghen LLVM_DEBUG(MI->dump()); 4906995e5daSNemanja Ivanovic MI->eraseFromParent(); 4916995e5daSNemanja Ivanovic NumRemovedInPreEmit++; 4926995e5daSNemanja Ivanovic } 4936995e5daSNemanja Ivanovic return Changed; 4946995e5daSNemanja Ivanovic } 4956995e5daSNemanja Ivanovic }; 4966995e5daSNemanja Ivanovic } 4976995e5daSNemanja Ivanovic 4986995e5daSNemanja Ivanovic INITIALIZE_PASS(PPCPreEmitPeephole, DEBUG_TYPE, "PowerPC Pre-Emit Peephole", 4996995e5daSNemanja Ivanovic false, false) 5006995e5daSNemanja Ivanovic char PPCPreEmitPeephole::ID = 0; 5016995e5daSNemanja Ivanovic 5026995e5daSNemanja Ivanovic FunctionPass *llvm::createPPCPreEmitPeepholePass() { 5036995e5daSNemanja Ivanovic return new PPCPreEmitPeephole(); 5046995e5daSNemanja Ivanovic } 505