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" 24*a60251d7SStefan 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> 424e1f5e07SNemanja Ivanovic RunPreEmitPeephole("ppc-late-peephole", cl::Hidden, cl::init(true), 436995e5daSNemanja Ivanovic cl::desc("Run pre-emit peephole optimizations.")); 446995e5daSNemanja Ivanovic 456995e5daSNemanja Ivanovic namespace { 46*a60251d7SStefan Pintilie 47*a60251d7SStefan Pintilie static bool hasPCRelativeForm(MachineInstr &Use) { 48*a60251d7SStefan Pintilie switch (Use.getOpcode()) { 49*a60251d7SStefan Pintilie default: 50*a60251d7SStefan Pintilie return false; 51*a60251d7SStefan Pintilie case PPC::LBZ: 52*a60251d7SStefan Pintilie case PPC::LBZ8: 53*a60251d7SStefan Pintilie case PPC::LHA: 54*a60251d7SStefan Pintilie case PPC::LHA8: 55*a60251d7SStefan Pintilie case PPC::LHZ: 56*a60251d7SStefan Pintilie case PPC::LHZ8: 57*a60251d7SStefan Pintilie case PPC::LWZ: 58*a60251d7SStefan Pintilie case PPC::LWZ8: 59*a60251d7SStefan Pintilie case PPC::STB: 60*a60251d7SStefan Pintilie case PPC::STB8: 61*a60251d7SStefan Pintilie case PPC::STH: 62*a60251d7SStefan Pintilie case PPC::STH8: 63*a60251d7SStefan Pintilie case PPC::STW: 64*a60251d7SStefan Pintilie case PPC::STW8: 65*a60251d7SStefan Pintilie case PPC::LD: 66*a60251d7SStefan Pintilie case PPC::STD: 67*a60251d7SStefan Pintilie case PPC::LWA: 68*a60251d7SStefan Pintilie case PPC::LXSD: 69*a60251d7SStefan Pintilie case PPC::LXSSP: 70*a60251d7SStefan Pintilie case PPC::LXV: 71*a60251d7SStefan Pintilie case PPC::STXSD: 72*a60251d7SStefan Pintilie case PPC::STXSSP: 73*a60251d7SStefan Pintilie case PPC::STXV: 74*a60251d7SStefan Pintilie case PPC::LFD: 75*a60251d7SStefan Pintilie case PPC::LFS: 76*a60251d7SStefan Pintilie case PPC::STFD: 77*a60251d7SStefan Pintilie case PPC::STFS: 78*a60251d7SStefan Pintilie case PPC::DFLOADf32: 79*a60251d7SStefan Pintilie case PPC::DFLOADf64: 80*a60251d7SStefan Pintilie case PPC::DFSTOREf32: 81*a60251d7SStefan Pintilie case PPC::DFSTOREf64: 82*a60251d7SStefan Pintilie return true; 83*a60251d7SStefan Pintilie } 84*a60251d7SStefan Pintilie } 85*a60251d7SStefan Pintilie 866995e5daSNemanja Ivanovic class PPCPreEmitPeephole : public MachineFunctionPass { 876995e5daSNemanja Ivanovic public: 886995e5daSNemanja Ivanovic static char ID; 896995e5daSNemanja Ivanovic PPCPreEmitPeephole() : MachineFunctionPass(ID) { 906995e5daSNemanja Ivanovic initializePPCPreEmitPeepholePass(*PassRegistry::getPassRegistry()); 916995e5daSNemanja Ivanovic } 926995e5daSNemanja Ivanovic 936995e5daSNemanja Ivanovic void getAnalysisUsage(AnalysisUsage &AU) const override { 946995e5daSNemanja Ivanovic MachineFunctionPass::getAnalysisUsage(AU); 956995e5daSNemanja Ivanovic } 966995e5daSNemanja Ivanovic 976995e5daSNemanja Ivanovic MachineFunctionProperties getRequiredProperties() const override { 986995e5daSNemanja Ivanovic return MachineFunctionProperties().set( 996995e5daSNemanja Ivanovic MachineFunctionProperties::Property::NoVRegs); 1006995e5daSNemanja Ivanovic } 1016995e5daSNemanja Ivanovic 10241a010a4SYi-Hong Lyu // This function removes any redundant load immediates. It has two level 10341a010a4SYi-Hong Lyu // loops - The outer loop finds the load immediates BBI that could be used 10441a010a4SYi-Hong Lyu // to replace following redundancy. The inner loop scans instructions that 10541a010a4SYi-Hong Lyu // after BBI to find redundancy and update kill/dead flags accordingly. If 10641a010a4SYi-Hong Lyu // AfterBBI is the same as BBI, it is redundant, otherwise any instructions 10741a010a4SYi-Hong Lyu // that modify the def register of BBI would break the scanning. 10841a010a4SYi-Hong Lyu // DeadOrKillToUnset is a pointer to the previous operand that had the 10941a010a4SYi-Hong Lyu // kill/dead flag set. It keeps track of the def register of BBI, the use 11041a010a4SYi-Hong Lyu // registers of AfterBBIs and the def registers of AfterBBIs. 11141a010a4SYi-Hong Lyu bool removeRedundantLIs(MachineBasicBlock &MBB, 11241a010a4SYi-Hong Lyu const TargetRegisterInfo *TRI) { 11341a010a4SYi-Hong Lyu LLVM_DEBUG(dbgs() << "Remove redundant load immediates from MBB:\n"; 11441a010a4SYi-Hong Lyu MBB.dump(); dbgs() << "\n"); 11541a010a4SYi-Hong Lyu 11641a010a4SYi-Hong Lyu DenseSet<MachineInstr *> InstrsToErase; 11741a010a4SYi-Hong Lyu for (auto BBI = MBB.instr_begin(); BBI != MBB.instr_end(); ++BBI) { 11841a010a4SYi-Hong Lyu // Skip load immediate that is marked to be erased later because it 11941a010a4SYi-Hong Lyu // cannot be used to replace any other instructions. 12041a010a4SYi-Hong Lyu if (InstrsToErase.find(&*BBI) != InstrsToErase.end()) 12141a010a4SYi-Hong Lyu continue; 12241a010a4SYi-Hong Lyu // Skip non-load immediate. 12341a010a4SYi-Hong Lyu unsigned Opc = BBI->getOpcode(); 12441a010a4SYi-Hong Lyu if (Opc != PPC::LI && Opc != PPC::LI8 && Opc != PPC::LIS && 12541a010a4SYi-Hong Lyu Opc != PPC::LIS8) 12641a010a4SYi-Hong Lyu continue; 12741a010a4SYi-Hong Lyu // Skip load immediate, where the operand is a relocation (e.g., $r3 = 12841a010a4SYi-Hong Lyu // LI target-flags(ppc-lo) %const.0). 12941a010a4SYi-Hong Lyu if (!BBI->getOperand(1).isImm()) 13041a010a4SYi-Hong Lyu continue; 13141a010a4SYi-Hong Lyu assert(BBI->getOperand(0).isReg() && 13241a010a4SYi-Hong Lyu "Expected a register for the first operand"); 13341a010a4SYi-Hong Lyu 13441a010a4SYi-Hong Lyu LLVM_DEBUG(dbgs() << "Scanning after load immediate: "; BBI->dump();); 13541a010a4SYi-Hong Lyu 1360c476111SDaniel Sanders Register Reg = BBI->getOperand(0).getReg(); 13741a010a4SYi-Hong Lyu int64_t Imm = BBI->getOperand(1).getImm(); 13841a010a4SYi-Hong Lyu MachineOperand *DeadOrKillToUnset = nullptr; 13941a010a4SYi-Hong Lyu if (BBI->getOperand(0).isDead()) { 14041a010a4SYi-Hong Lyu DeadOrKillToUnset = &BBI->getOperand(0); 14141a010a4SYi-Hong Lyu LLVM_DEBUG(dbgs() << " Kill flag of " << *DeadOrKillToUnset 14241a010a4SYi-Hong Lyu << " from load immediate " << *BBI 14341a010a4SYi-Hong Lyu << " is a unsetting candidate\n"); 14441a010a4SYi-Hong Lyu } 14541a010a4SYi-Hong Lyu // This loop scans instructions after BBI to see if there is any 14641a010a4SYi-Hong Lyu // redundant load immediate. 14741a010a4SYi-Hong Lyu for (auto AfterBBI = std::next(BBI); AfterBBI != MBB.instr_end(); 14841a010a4SYi-Hong Lyu ++AfterBBI) { 14941a010a4SYi-Hong Lyu // Track the operand that kill Reg. We would unset the kill flag of 15041a010a4SYi-Hong Lyu // the operand if there is a following redundant load immediate. 15141a010a4SYi-Hong Lyu int KillIdx = AfterBBI->findRegisterUseOperandIdx(Reg, true, TRI); 1527f3787c0SNemanja Ivanovic 1537f3787c0SNemanja Ivanovic // We can't just clear implicit kills, so if we encounter one, stop 1547f3787c0SNemanja Ivanovic // looking further. 1557f3787c0SNemanja Ivanovic if (KillIdx != -1 && AfterBBI->getOperand(KillIdx).isImplicit()) { 1567f3787c0SNemanja Ivanovic LLVM_DEBUG(dbgs() 1577f3787c0SNemanja Ivanovic << "Encountered an implicit kill, cannot proceed: "); 1587f3787c0SNemanja Ivanovic LLVM_DEBUG(AfterBBI->dump()); 1597f3787c0SNemanja Ivanovic break; 1607f3787c0SNemanja Ivanovic } 1617f3787c0SNemanja Ivanovic 16241a010a4SYi-Hong Lyu if (KillIdx != -1) { 16341a010a4SYi-Hong Lyu assert(!DeadOrKillToUnset && "Shouldn't kill same register twice"); 16441a010a4SYi-Hong Lyu DeadOrKillToUnset = &AfterBBI->getOperand(KillIdx); 16541a010a4SYi-Hong Lyu LLVM_DEBUG(dbgs() 16641a010a4SYi-Hong Lyu << " Kill flag of " << *DeadOrKillToUnset << " from " 16741a010a4SYi-Hong Lyu << *AfterBBI << " is a unsetting candidate\n"); 16841a010a4SYi-Hong Lyu } 16941a010a4SYi-Hong Lyu 17041a010a4SYi-Hong Lyu if (!AfterBBI->modifiesRegister(Reg, TRI)) 17141a010a4SYi-Hong Lyu continue; 17241a010a4SYi-Hong Lyu // Finish scanning because Reg is overwritten by a non-load 17341a010a4SYi-Hong Lyu // instruction. 17441a010a4SYi-Hong Lyu if (AfterBBI->getOpcode() != Opc) 17541a010a4SYi-Hong Lyu break; 17641a010a4SYi-Hong Lyu assert(AfterBBI->getOperand(0).isReg() && 17741a010a4SYi-Hong Lyu "Expected a register for the first operand"); 17841a010a4SYi-Hong Lyu // Finish scanning because Reg is overwritten by a relocation or a 17941a010a4SYi-Hong Lyu // different value. 18041a010a4SYi-Hong Lyu if (!AfterBBI->getOperand(1).isImm() || 18141a010a4SYi-Hong Lyu AfterBBI->getOperand(1).getImm() != Imm) 18241a010a4SYi-Hong Lyu break; 18341a010a4SYi-Hong Lyu 18441a010a4SYi-Hong Lyu // It loads same immediate value to the same Reg, which is redundant. 18541a010a4SYi-Hong Lyu // We would unset kill flag in previous Reg usage to extend live range 18641a010a4SYi-Hong Lyu // of Reg first, then remove the redundancy. 1872fbfb04fSYi-Hong Lyu if (DeadOrKillToUnset) { 1882fbfb04fSYi-Hong Lyu LLVM_DEBUG(dbgs() 1892fbfb04fSYi-Hong Lyu << " Unset dead/kill flag of " << *DeadOrKillToUnset 19041a010a4SYi-Hong Lyu << " from " << *DeadOrKillToUnset->getParent()); 19141a010a4SYi-Hong Lyu if (DeadOrKillToUnset->isDef()) 19241a010a4SYi-Hong Lyu DeadOrKillToUnset->setIsDead(false); 19341a010a4SYi-Hong Lyu else 19441a010a4SYi-Hong Lyu DeadOrKillToUnset->setIsKill(false); 1952fbfb04fSYi-Hong Lyu } 19641a010a4SYi-Hong Lyu DeadOrKillToUnset = 19741a010a4SYi-Hong Lyu AfterBBI->findRegisterDefOperand(Reg, true, true, TRI); 19841a010a4SYi-Hong Lyu if (DeadOrKillToUnset) 19941a010a4SYi-Hong Lyu LLVM_DEBUG(dbgs() 20041a010a4SYi-Hong Lyu << " Dead flag of " << *DeadOrKillToUnset << " from " 20141a010a4SYi-Hong Lyu << *AfterBBI << " is a unsetting candidate\n"); 20241a010a4SYi-Hong Lyu InstrsToErase.insert(&*AfterBBI); 20341a010a4SYi-Hong Lyu LLVM_DEBUG(dbgs() << " Remove redundant load immediate: "; 20441a010a4SYi-Hong Lyu AfterBBI->dump()); 20541a010a4SYi-Hong Lyu } 20641a010a4SYi-Hong Lyu } 20741a010a4SYi-Hong Lyu 20841a010a4SYi-Hong Lyu for (MachineInstr *MI : InstrsToErase) { 20941a010a4SYi-Hong Lyu MI->eraseFromParent(); 21041a010a4SYi-Hong Lyu } 21141a010a4SYi-Hong Lyu NumRemovedInPreEmit += InstrsToErase.size(); 21241a010a4SYi-Hong Lyu return !InstrsToErase.empty(); 21341a010a4SYi-Hong Lyu } 21441a010a4SYi-Hong Lyu 215*a60251d7SStefan Pintilie // Check if this instruction is a PLDpc that is part of a GOT indirect 216*a60251d7SStefan Pintilie // access. 217*a60251d7SStefan Pintilie bool isGOTPLDpc(MachineInstr &Instr) { 218*a60251d7SStefan Pintilie if (Instr.getOpcode() != PPC::PLDpc) 219*a60251d7SStefan Pintilie return false; 220*a60251d7SStefan Pintilie 221*a60251d7SStefan Pintilie // The result must be a register. 222*a60251d7SStefan Pintilie const MachineOperand &LoadedAddressReg = Instr.getOperand(0); 223*a60251d7SStefan Pintilie if (!LoadedAddressReg.isReg()) 224*a60251d7SStefan Pintilie return false; 225*a60251d7SStefan Pintilie 226*a60251d7SStefan Pintilie // Make sure that this is a global symbol. 227*a60251d7SStefan Pintilie const MachineOperand &SymbolOp = Instr.getOperand(1); 228*a60251d7SStefan Pintilie if (!SymbolOp.isGlobal()) 229*a60251d7SStefan Pintilie return false; 230*a60251d7SStefan Pintilie 231*a60251d7SStefan Pintilie // Finally return true only if the GOT flag is present. 232*a60251d7SStefan Pintilie return (SymbolOp.getTargetFlags() & PPCII::MO_GOT_FLAG); 233*a60251d7SStefan Pintilie } 234*a60251d7SStefan Pintilie 235*a60251d7SStefan Pintilie bool addLinkerOpt(MachineBasicBlock &MBB, const TargetRegisterInfo *TRI) { 236*a60251d7SStefan Pintilie MachineFunction *MF = MBB.getParent(); 237*a60251d7SStefan Pintilie // Add this linker opt only if we are using PC Relative memops. 238*a60251d7SStefan Pintilie if (!MF->getSubtarget<PPCSubtarget>().isUsingPCRelativeCalls()) 239*a60251d7SStefan Pintilie return false; 240*a60251d7SStefan Pintilie 241*a60251d7SStefan Pintilie // Struct to keep track of one def/use pair for a GOT indirect access. 242*a60251d7SStefan Pintilie struct GOTDefUsePair { 243*a60251d7SStefan Pintilie MachineBasicBlock::iterator DefInst; 244*a60251d7SStefan Pintilie MachineBasicBlock::iterator UseInst; 245*a60251d7SStefan Pintilie Register DefReg; 246*a60251d7SStefan Pintilie Register UseReg; 247*a60251d7SStefan Pintilie bool StillValid; 248*a60251d7SStefan Pintilie }; 249*a60251d7SStefan Pintilie // Vector of def/ues pairs in this basic block. 250*a60251d7SStefan Pintilie SmallVector<GOTDefUsePair, 4> CandPairs; 251*a60251d7SStefan Pintilie SmallVector<GOTDefUsePair, 4> ValidPairs; 252*a60251d7SStefan Pintilie bool MadeChange = false; 253*a60251d7SStefan Pintilie 254*a60251d7SStefan Pintilie // Run through all of the instructions in the basic block and try to 255*a60251d7SStefan Pintilie // collect potential pairs of GOT indirect access instructions. 256*a60251d7SStefan Pintilie for (auto BBI = MBB.instr_begin(); BBI != MBB.instr_end(); ++BBI) { 257*a60251d7SStefan Pintilie // Look for the initial GOT indirect load. 258*a60251d7SStefan Pintilie if (isGOTPLDpc(*BBI)) { 259*a60251d7SStefan Pintilie GOTDefUsePair CurrentPair{BBI, MachineBasicBlock::iterator(), 260*a60251d7SStefan Pintilie BBI->getOperand(0).getReg(), 261*a60251d7SStefan Pintilie PPC::NoRegister, true}; 262*a60251d7SStefan Pintilie CandPairs.push_back(CurrentPair); 263*a60251d7SStefan Pintilie continue; 264*a60251d7SStefan Pintilie } 265*a60251d7SStefan Pintilie 266*a60251d7SStefan Pintilie // We haven't encountered any new PLD instructions, nothing to check. 267*a60251d7SStefan Pintilie if (CandPairs.empty()) 268*a60251d7SStefan Pintilie continue; 269*a60251d7SStefan Pintilie 270*a60251d7SStefan Pintilie // Run through the candidate pairs and see if any of the registers 271*a60251d7SStefan Pintilie // defined in the PLD instructions are used by this instruction. 272*a60251d7SStefan Pintilie // Note: the size of CandPairs can change in the loop. 273*a60251d7SStefan Pintilie for (unsigned Idx = 0; Idx < CandPairs.size(); Idx++) { 274*a60251d7SStefan Pintilie GOTDefUsePair &Pair = CandPairs[Idx]; 275*a60251d7SStefan Pintilie // The instruction does not use or modify this PLD's def reg, 276*a60251d7SStefan Pintilie // ignore it. 277*a60251d7SStefan Pintilie if (!BBI->readsRegister(Pair.DefReg, TRI) && 278*a60251d7SStefan Pintilie !BBI->modifiesRegister(Pair.DefReg, TRI)) 279*a60251d7SStefan Pintilie continue; 280*a60251d7SStefan Pintilie 281*a60251d7SStefan Pintilie // The use needs to be used in the address compuation and not 282*a60251d7SStefan Pintilie // as the register being stored for a store. 283*a60251d7SStefan Pintilie const MachineOperand *UseOp = 284*a60251d7SStefan Pintilie hasPCRelativeForm(*BBI) ? &BBI->getOperand(2) : nullptr; 285*a60251d7SStefan Pintilie 286*a60251d7SStefan Pintilie // Check for a valid use. 287*a60251d7SStefan Pintilie if (UseOp && UseOp->isReg() && UseOp->getReg() == Pair.DefReg && 288*a60251d7SStefan Pintilie UseOp->isUse() && UseOp->isKill()) { 289*a60251d7SStefan Pintilie Pair.UseInst = BBI; 290*a60251d7SStefan Pintilie Pair.UseReg = BBI->getOperand(0).getReg(); 291*a60251d7SStefan Pintilie ValidPairs.push_back(Pair); 292*a60251d7SStefan Pintilie } 293*a60251d7SStefan Pintilie CandPairs.erase(CandPairs.begin() + Idx); 294*a60251d7SStefan Pintilie } 295*a60251d7SStefan Pintilie } 296*a60251d7SStefan Pintilie 297*a60251d7SStefan Pintilie // Go through all of the pairs and check for any more valid uses. 298*a60251d7SStefan Pintilie for (auto Pair = ValidPairs.begin(); Pair != ValidPairs.end(); Pair++) { 299*a60251d7SStefan Pintilie // We shouldn't be here if we don't have a valid pair. 300*a60251d7SStefan Pintilie assert(Pair->UseInst.isValid() && Pair->StillValid && 301*a60251d7SStefan Pintilie "Kept an invalid def/use pair for GOT PCRel opt"); 302*a60251d7SStefan Pintilie // We have found a potential pair. Search through the instructions 303*a60251d7SStefan Pintilie // between the def and the use to see if it is valid to mark this as a 304*a60251d7SStefan Pintilie // linker opt. 305*a60251d7SStefan Pintilie MachineBasicBlock::iterator BBI = Pair->DefInst; 306*a60251d7SStefan Pintilie ++BBI; 307*a60251d7SStefan Pintilie for (; BBI != Pair->UseInst; ++BBI) { 308*a60251d7SStefan Pintilie if (BBI->readsRegister(Pair->UseReg, TRI) || 309*a60251d7SStefan Pintilie BBI->modifiesRegister(Pair->UseReg, TRI)) { 310*a60251d7SStefan Pintilie Pair->StillValid = false; 311*a60251d7SStefan Pintilie break; 312*a60251d7SStefan Pintilie } 313*a60251d7SStefan Pintilie } 314*a60251d7SStefan Pintilie 315*a60251d7SStefan Pintilie if (!Pair->StillValid) 316*a60251d7SStefan Pintilie continue; 317*a60251d7SStefan Pintilie 318*a60251d7SStefan Pintilie // The load/store instruction that uses the address from the PLD will 319*a60251d7SStefan Pintilie // either use a register (for a store) or define a register (for the 320*a60251d7SStefan Pintilie // load). That register will be added as an implicit def to the PLD 321*a60251d7SStefan Pintilie // and as an implicit use on the second memory op. This is a precaution 322*a60251d7SStefan Pintilie // to prevent future passes from using that register between the two 323*a60251d7SStefan Pintilie // instructions. 324*a60251d7SStefan Pintilie MachineOperand ImplDef = 325*a60251d7SStefan Pintilie MachineOperand::CreateReg(Pair->UseReg, true, true); 326*a60251d7SStefan Pintilie MachineOperand ImplUse = 327*a60251d7SStefan Pintilie MachineOperand::CreateReg(Pair->UseReg, false, true); 328*a60251d7SStefan Pintilie Pair->DefInst->addOperand(ImplDef); 329*a60251d7SStefan Pintilie Pair->UseInst->addOperand(ImplUse); 330*a60251d7SStefan Pintilie 331*a60251d7SStefan Pintilie // Create the symbol. 332*a60251d7SStefan Pintilie MCContext &Context = MF->getContext(); 333*a60251d7SStefan Pintilie MCSymbol *Symbol = 334*a60251d7SStefan Pintilie Context.createTempSymbol(Twine("pcrel"), false, false); 335*a60251d7SStefan Pintilie MachineOperand PCRelLabel = 336*a60251d7SStefan Pintilie MachineOperand::CreateMCSymbol(Symbol, PPCII::MO_PCREL_OPT_FLAG); 337*a60251d7SStefan Pintilie Pair->DefInst->addOperand(*MF, PCRelLabel); 338*a60251d7SStefan Pintilie Pair->UseInst->addOperand(*MF, PCRelLabel); 339*a60251d7SStefan Pintilie MadeChange |= true; 340*a60251d7SStefan Pintilie } 341*a60251d7SStefan Pintilie return MadeChange; 342*a60251d7SStefan Pintilie } 343*a60251d7SStefan Pintilie 3446995e5daSNemanja Ivanovic bool runOnMachineFunction(MachineFunction &MF) override { 345a3db9c08SYi-Hong Lyu if (skipFunction(MF.getFunction()) || !RunPreEmitPeephole) { 346a3db9c08SYi-Hong Lyu // Remove UNENCODED_NOP even when this pass is disabled. 347a3db9c08SYi-Hong Lyu // This needs to be done unconditionally so we don't emit zeros 348a3db9c08SYi-Hong Lyu // in the instruction stream. 349a3db9c08SYi-Hong Lyu SmallVector<MachineInstr *, 4> InstrsToErase; 350a3db9c08SYi-Hong Lyu for (MachineBasicBlock &MBB : MF) 351a3db9c08SYi-Hong Lyu for (MachineInstr &MI : MBB) 352a3db9c08SYi-Hong Lyu if (MI.getOpcode() == PPC::UNENCODED_NOP) 353a3db9c08SYi-Hong Lyu InstrsToErase.push_back(&MI); 354a3db9c08SYi-Hong Lyu for (MachineInstr *MI : InstrsToErase) 355a3db9c08SYi-Hong Lyu MI->eraseFromParent(); 3566995e5daSNemanja Ivanovic return false; 357a3db9c08SYi-Hong Lyu } 3586995e5daSNemanja Ivanovic bool Changed = false; 3596995e5daSNemanja Ivanovic const PPCInstrInfo *TII = MF.getSubtarget<PPCSubtarget>().getInstrInfo(); 36020982f09SHiroshi Inoue const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 3616995e5daSNemanja Ivanovic SmallVector<MachineInstr *, 4> InstrsToErase; 3626995e5daSNemanja Ivanovic for (MachineBasicBlock &MBB : MF) { 36341a010a4SYi-Hong Lyu Changed |= removeRedundantLIs(MBB, TRI); 364*a60251d7SStefan Pintilie Changed |= addLinkerOpt(MBB, TRI); 3656995e5daSNemanja Ivanovic for (MachineInstr &MI : MBB) { 3664c0b110eSNemanja Ivanovic unsigned Opc = MI.getOpcode(); 367a3db9c08SYi-Hong Lyu if (Opc == PPC::UNENCODED_NOP) { 368a3db9c08SYi-Hong Lyu InstrsToErase.push_back(&MI); 369a3db9c08SYi-Hong Lyu continue; 370a3db9c08SYi-Hong Lyu } 3714c0b110eSNemanja Ivanovic // Detect self copies - these can result from running AADB. 3724c0b110eSNemanja Ivanovic if (PPCInstrInfo::isSameClassPhysRegCopy(Opc)) { 3734c0b110eSNemanja Ivanovic const MCInstrDesc &MCID = TII->get(Opc); 3744c0b110eSNemanja Ivanovic if (MCID.getNumOperands() == 3 && 3754c0b110eSNemanja Ivanovic MI.getOperand(0).getReg() == MI.getOperand(1).getReg() && 3764c0b110eSNemanja Ivanovic MI.getOperand(0).getReg() == MI.getOperand(2).getReg()) { 3774c0b110eSNemanja Ivanovic NumberOfSelfCopies++; 3784c0b110eSNemanja Ivanovic LLVM_DEBUG(dbgs() << "Deleting self-copy instruction: "); 3794c0b110eSNemanja Ivanovic LLVM_DEBUG(MI.dump()); 3804c0b110eSNemanja Ivanovic InstrsToErase.push_back(&MI); 3814c0b110eSNemanja Ivanovic continue; 3824c0b110eSNemanja Ivanovic } 3834c0b110eSNemanja Ivanovic else if (MCID.getNumOperands() == 2 && 3844c0b110eSNemanja Ivanovic MI.getOperand(0).getReg() == MI.getOperand(1).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 } 3926995e5daSNemanja Ivanovic MachineInstr *DefMIToErase = nullptr; 3936995e5daSNemanja Ivanovic if (TII->convertToImmediateForm(MI, &DefMIToErase)) { 3946995e5daSNemanja Ivanovic Changed = true; 3956995e5daSNemanja Ivanovic NumRRConvertedInPreEmit++; 396d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Converted instruction to imm form: "); 397d34e60caSNicola Zaghen LLVM_DEBUG(MI.dump()); 3986995e5daSNemanja Ivanovic if (DefMIToErase) { 3996995e5daSNemanja Ivanovic InstrsToErase.push_back(DefMIToErase); 4006995e5daSNemanja Ivanovic } 4016995e5daSNemanja Ivanovic } 40282205914Sczhengsz if (TII->foldFrameOffset(MI)) { 40382205914Sczhengsz Changed = true; 40482205914Sczhengsz NumFrameOffFoldInPreEmit++; 40582205914Sczhengsz LLVM_DEBUG(dbgs() << "Frame offset folding by using index form: "); 40682205914Sczhengsz LLVM_DEBUG(MI.dump()); 40782205914Sczhengsz } 4086995e5daSNemanja Ivanovic } 40920982f09SHiroshi Inoue 41020982f09SHiroshi Inoue // Eliminate conditional branch based on a constant CR bit by 41120982f09SHiroshi Inoue // CRSET or CRUNSET. We eliminate the conditional branch or 41220982f09SHiroshi Inoue // convert it into an unconditional branch. Also, if the CR bit 41320982f09SHiroshi Inoue // is not used by other instructions, we eliminate CRSET as well. 41420982f09SHiroshi Inoue auto I = MBB.getFirstInstrTerminator(); 41520982f09SHiroshi Inoue if (I == MBB.instr_end()) 41620982f09SHiroshi Inoue continue; 41720982f09SHiroshi Inoue MachineInstr *Br = &*I; 41820982f09SHiroshi Inoue if (Br->getOpcode() != PPC::BC && Br->getOpcode() != PPC::BCn) 41920982f09SHiroshi Inoue continue; 42020982f09SHiroshi Inoue MachineInstr *CRSetMI = nullptr; 4210c476111SDaniel Sanders Register CRBit = Br->getOperand(0).getReg(); 42220982f09SHiroshi Inoue unsigned CRReg = getCRFromCRBit(CRBit); 42320982f09SHiroshi Inoue bool SeenUse = false; 42420982f09SHiroshi Inoue MachineBasicBlock::reverse_iterator It = Br, Er = MBB.rend(); 42520982f09SHiroshi Inoue for (It++; It != Er; It++) { 42620982f09SHiroshi Inoue if (It->modifiesRegister(CRBit, TRI)) { 42720982f09SHiroshi Inoue if ((It->getOpcode() == PPC::CRUNSET || 42820982f09SHiroshi Inoue It->getOpcode() == PPC::CRSET) && 42920982f09SHiroshi Inoue It->getOperand(0).getReg() == CRBit) 43020982f09SHiroshi Inoue CRSetMI = &*It; 43120982f09SHiroshi Inoue break; 43220982f09SHiroshi Inoue } 43320982f09SHiroshi Inoue if (It->readsRegister(CRBit, TRI)) 43420982f09SHiroshi Inoue SeenUse = true; 43520982f09SHiroshi Inoue } 43620982f09SHiroshi Inoue if (!CRSetMI) continue; 43720982f09SHiroshi Inoue 43820982f09SHiroshi Inoue unsigned CRSetOp = CRSetMI->getOpcode(); 43920982f09SHiroshi Inoue if ((Br->getOpcode() == PPC::BCn && CRSetOp == PPC::CRSET) || 44020982f09SHiroshi Inoue (Br->getOpcode() == PPC::BC && CRSetOp == PPC::CRUNSET)) { 44120982f09SHiroshi Inoue // Remove this branch since it cannot be taken. 44220982f09SHiroshi Inoue InstrsToErase.push_back(Br); 44320982f09SHiroshi Inoue MBB.removeSuccessor(Br->getOperand(1).getMBB()); 44420982f09SHiroshi Inoue } 44520982f09SHiroshi Inoue else { 44620982f09SHiroshi Inoue // This conditional branch is always taken. So, remove all branches 44720982f09SHiroshi Inoue // and insert an unconditional branch to the destination of this. 44820982f09SHiroshi Inoue MachineBasicBlock::iterator It = Br, Er = MBB.end(); 449ecc89b76SWei Mi for (; It != Er; It++) { 45020982f09SHiroshi Inoue if (It->isDebugInstr()) continue; 45120982f09SHiroshi Inoue assert(It->isTerminator() && "Non-terminator after a terminator"); 45220982f09SHiroshi Inoue InstrsToErase.push_back(&*It); 45320982f09SHiroshi Inoue } 45420982f09SHiroshi Inoue if (!MBB.isLayoutSuccessor(Br->getOperand(1).getMBB())) { 45520982f09SHiroshi Inoue ArrayRef<MachineOperand> NoCond; 45620982f09SHiroshi Inoue TII->insertBranch(MBB, Br->getOperand(1).getMBB(), nullptr, 45720982f09SHiroshi Inoue NoCond, Br->getDebugLoc()); 45820982f09SHiroshi Inoue } 45920982f09SHiroshi Inoue for (auto &Succ : MBB.successors()) 46020982f09SHiroshi Inoue if (Succ != Br->getOperand(1).getMBB()) { 46120982f09SHiroshi Inoue MBB.removeSuccessor(Succ); 46220982f09SHiroshi Inoue break; 46320982f09SHiroshi Inoue } 46420982f09SHiroshi Inoue } 46520982f09SHiroshi Inoue 46620982f09SHiroshi Inoue // If the CRBit is not used by another instruction, we can eliminate 46720982f09SHiroshi Inoue // CRSET/CRUNSET instruction. 46820982f09SHiroshi Inoue if (!SeenUse) { 46920982f09SHiroshi Inoue // We need to check use of the CRBit in successors. 47020982f09SHiroshi Inoue for (auto &SuccMBB : MBB.successors()) 47120982f09SHiroshi Inoue if (SuccMBB->isLiveIn(CRBit) || SuccMBB->isLiveIn(CRReg)) { 47220982f09SHiroshi Inoue SeenUse = true; 47320982f09SHiroshi Inoue break; 47420982f09SHiroshi Inoue } 47520982f09SHiroshi Inoue if (!SeenUse) 47620982f09SHiroshi Inoue InstrsToErase.push_back(CRSetMI); 47720982f09SHiroshi Inoue } 4786995e5daSNemanja Ivanovic } 4796995e5daSNemanja Ivanovic for (MachineInstr *MI : InstrsToErase) { 480d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "PPC pre-emit peephole: erasing instruction: "); 481d34e60caSNicola Zaghen LLVM_DEBUG(MI->dump()); 4826995e5daSNemanja Ivanovic MI->eraseFromParent(); 4836995e5daSNemanja Ivanovic NumRemovedInPreEmit++; 4846995e5daSNemanja Ivanovic } 4856995e5daSNemanja Ivanovic return Changed; 4866995e5daSNemanja Ivanovic } 4876995e5daSNemanja Ivanovic }; 4886995e5daSNemanja Ivanovic } 4896995e5daSNemanja Ivanovic 4906995e5daSNemanja Ivanovic INITIALIZE_PASS(PPCPreEmitPeephole, DEBUG_TYPE, "PowerPC Pre-Emit Peephole", 4916995e5daSNemanja Ivanovic false, false) 4926995e5daSNemanja Ivanovic char PPCPreEmitPeephole::ID = 0; 4936995e5daSNemanja Ivanovic 4946995e5daSNemanja Ivanovic FunctionPass *llvm::createPPCPreEmitPeepholePass() { 4956995e5daSNemanja Ivanovic return new PPCPreEmitPeephole(); 4966995e5daSNemanja Ivanovic } 497