1*81ad6265SDimitry Andric //===-- PPCCTRLoops.cpp - Verify CTR loops -----------------===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric // 9*81ad6265SDimitry Andric // This pass verifies that all bdnz/bdz instructions are dominated by a loop 10*81ad6265SDimitry Andric // mtctr before any other instructions that might clobber the ctr register. 11*81ad6265SDimitry Andric // 12*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 13*81ad6265SDimitry Andric 14*81ad6265SDimitry Andric // CTR loops are produced by the HardwareLoops pass and this pass is simply a 15*81ad6265SDimitry Andric // verification that no invalid CTR loops are produced. As such, it isn't 16*81ad6265SDimitry Andric // something that needs to be run (or even defined) for Release builds so the 17*81ad6265SDimitry Andric // entire file is guarded by NDEBUG. 18*81ad6265SDimitry Andric #ifndef NDEBUG 19*81ad6265SDimitry Andric #include <vector> 20*81ad6265SDimitry Andric 21*81ad6265SDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h" 22*81ad6265SDimitry Andric #include "PPC.h" 23*81ad6265SDimitry Andric #include "llvm/ADT/SmallSet.h" 24*81ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h" 25*81ad6265SDimitry Andric #include "llvm/ADT/StringRef.h" 26*81ad6265SDimitry Andric #include "llvm/ADT/ilist_iterator.h" 27*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 28*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 29*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 30*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 31*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 32*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineInstrBundleIterator.h" 33*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 34*81ad6265SDimitry Andric #include "llvm/CodeGen/Register.h" 35*81ad6265SDimitry Andric #include "llvm/InitializePasses.h" 36*81ad6265SDimitry Andric #include "llvm/Pass.h" 37*81ad6265SDimitry Andric #include "llvm/PassRegistry.h" 38*81ad6265SDimitry Andric #include "llvm/Support/CodeGen.h" 39*81ad6265SDimitry Andric #include "llvm/Support/Debug.h" 40*81ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h" 41*81ad6265SDimitry Andric #include "llvm/Support/GenericDomTreeConstruction.h" 42*81ad6265SDimitry Andric #include "llvm/Support/Printable.h" 43*81ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h" 44*81ad6265SDimitry Andric 45*81ad6265SDimitry Andric using namespace llvm; 46*81ad6265SDimitry Andric 47*81ad6265SDimitry Andric #define DEBUG_TYPE "ppc-ctrloops-verify" 48*81ad6265SDimitry Andric 49*81ad6265SDimitry Andric namespace { 50*81ad6265SDimitry Andric 51*81ad6265SDimitry Andric struct PPCCTRLoopsVerify : public MachineFunctionPass { 52*81ad6265SDimitry Andric public: 53*81ad6265SDimitry Andric static char ID; 54*81ad6265SDimitry Andric 55*81ad6265SDimitry Andric PPCCTRLoopsVerify() : MachineFunctionPass(ID) { 56*81ad6265SDimitry Andric initializePPCCTRLoopsVerifyPass(*PassRegistry::getPassRegistry()); 57*81ad6265SDimitry Andric } 58*81ad6265SDimitry Andric 59*81ad6265SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 60*81ad6265SDimitry Andric AU.addRequired<MachineDominatorTree>(); 61*81ad6265SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 62*81ad6265SDimitry Andric } 63*81ad6265SDimitry Andric 64*81ad6265SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 65*81ad6265SDimitry Andric 66*81ad6265SDimitry Andric private: 67*81ad6265SDimitry Andric MachineDominatorTree *MDT; 68*81ad6265SDimitry Andric }; 69*81ad6265SDimitry Andric 70*81ad6265SDimitry Andric char PPCCTRLoopsVerify::ID = 0; 71*81ad6265SDimitry Andric } // end anonymous namespace 72*81ad6265SDimitry Andric 73*81ad6265SDimitry Andric INITIALIZE_PASS_BEGIN(PPCCTRLoopsVerify, "ppc-ctr-loops-verify", 74*81ad6265SDimitry Andric "PowerPC CTR Loops Verify", false, false) 75*81ad6265SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) 76*81ad6265SDimitry Andric INITIALIZE_PASS_END(PPCCTRLoopsVerify, "ppc-ctr-loops-verify", 77*81ad6265SDimitry Andric "PowerPC CTR Loops Verify", false, false) 78*81ad6265SDimitry Andric 79*81ad6265SDimitry Andric FunctionPass *llvm::createPPCCTRLoopsVerify() { 80*81ad6265SDimitry Andric return new PPCCTRLoopsVerify(); 81*81ad6265SDimitry Andric } 82*81ad6265SDimitry Andric 83*81ad6265SDimitry Andric static bool clobbersCTR(const MachineInstr &MI) { 84*81ad6265SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 85*81ad6265SDimitry Andric if (MO.isReg()) { 86*81ad6265SDimitry Andric if (MO.isDef() && (MO.getReg() == PPC::CTR || MO.getReg() == PPC::CTR8)) 87*81ad6265SDimitry Andric return true; 88*81ad6265SDimitry Andric } else if (MO.isRegMask()) { 89*81ad6265SDimitry Andric if (MO.clobbersPhysReg(PPC::CTR) || MO.clobbersPhysReg(PPC::CTR8)) 90*81ad6265SDimitry Andric return true; 91*81ad6265SDimitry Andric } 92*81ad6265SDimitry Andric } 93*81ad6265SDimitry Andric 94*81ad6265SDimitry Andric return false; 95*81ad6265SDimitry Andric } 96*81ad6265SDimitry Andric 97*81ad6265SDimitry Andric static bool verifyCTRBranch(MachineBasicBlock *MBB, 98*81ad6265SDimitry Andric MachineBasicBlock::iterator I) { 99*81ad6265SDimitry Andric MachineBasicBlock::iterator BI = I; 100*81ad6265SDimitry Andric SmallSet<MachineBasicBlock *, 16> Visited; 101*81ad6265SDimitry Andric SmallVector<MachineBasicBlock *, 8> Preds; 102*81ad6265SDimitry Andric bool CheckPreds; 103*81ad6265SDimitry Andric 104*81ad6265SDimitry Andric if (I == MBB->begin()) { 105*81ad6265SDimitry Andric Visited.insert(MBB); 106*81ad6265SDimitry Andric goto queue_preds; 107*81ad6265SDimitry Andric } else 108*81ad6265SDimitry Andric --I; 109*81ad6265SDimitry Andric 110*81ad6265SDimitry Andric check_block: 111*81ad6265SDimitry Andric Visited.insert(MBB); 112*81ad6265SDimitry Andric if (I == MBB->end()) 113*81ad6265SDimitry Andric goto queue_preds; 114*81ad6265SDimitry Andric 115*81ad6265SDimitry Andric CheckPreds = true; 116*81ad6265SDimitry Andric for (MachineBasicBlock::iterator IE = MBB->begin();; --I) { 117*81ad6265SDimitry Andric unsigned Opc = I->getOpcode(); 118*81ad6265SDimitry Andric if (Opc == PPC::MTCTRloop || Opc == PPC::MTCTR8loop) { 119*81ad6265SDimitry Andric CheckPreds = false; 120*81ad6265SDimitry Andric break; 121*81ad6265SDimitry Andric } 122*81ad6265SDimitry Andric 123*81ad6265SDimitry Andric if (I != BI && clobbersCTR(*I)) { 124*81ad6265SDimitry Andric LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " (" << MBB->getFullName() 125*81ad6265SDimitry Andric << ") instruction " << *I 126*81ad6265SDimitry Andric << " clobbers CTR, invalidating " 127*81ad6265SDimitry Andric << printMBBReference(*BI->getParent()) << " (" 128*81ad6265SDimitry Andric << BI->getParent()->getFullName() << ") instruction " 129*81ad6265SDimitry Andric << *BI << "\n"); 130*81ad6265SDimitry Andric return false; 131*81ad6265SDimitry Andric } 132*81ad6265SDimitry Andric 133*81ad6265SDimitry Andric if (I == IE) 134*81ad6265SDimitry Andric break; 135*81ad6265SDimitry Andric } 136*81ad6265SDimitry Andric 137*81ad6265SDimitry Andric if (!CheckPreds && Preds.empty()) 138*81ad6265SDimitry Andric return true; 139*81ad6265SDimitry Andric 140*81ad6265SDimitry Andric if (CheckPreds) { 141*81ad6265SDimitry Andric queue_preds: 142*81ad6265SDimitry Andric if (MachineFunction::iterator(MBB) == MBB->getParent()->begin()) { 143*81ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Unable to find a MTCTR instruction for " 144*81ad6265SDimitry Andric << printMBBReference(*BI->getParent()) << " (" 145*81ad6265SDimitry Andric << BI->getParent()->getFullName() << ") instruction " 146*81ad6265SDimitry Andric << *BI << "\n"); 147*81ad6265SDimitry Andric return false; 148*81ad6265SDimitry Andric } 149*81ad6265SDimitry Andric 150*81ad6265SDimitry Andric append_range(Preds, MBB->predecessors()); 151*81ad6265SDimitry Andric } 152*81ad6265SDimitry Andric 153*81ad6265SDimitry Andric do { 154*81ad6265SDimitry Andric MBB = Preds.pop_back_val(); 155*81ad6265SDimitry Andric if (!Visited.count(MBB)) { 156*81ad6265SDimitry Andric I = MBB->getLastNonDebugInstr(); 157*81ad6265SDimitry Andric goto check_block; 158*81ad6265SDimitry Andric } 159*81ad6265SDimitry Andric } while (!Preds.empty()); 160*81ad6265SDimitry Andric 161*81ad6265SDimitry Andric return true; 162*81ad6265SDimitry Andric } 163*81ad6265SDimitry Andric 164*81ad6265SDimitry Andric bool PPCCTRLoopsVerify::runOnMachineFunction(MachineFunction &MF) { 165*81ad6265SDimitry Andric MDT = &getAnalysis<MachineDominatorTree>(); 166*81ad6265SDimitry Andric 167*81ad6265SDimitry Andric // Verify that all bdnz/bdz instructions are dominated by a loop mtctr before 168*81ad6265SDimitry Andric // any other instructions that might clobber the ctr register. 169*81ad6265SDimitry Andric for (MachineBasicBlock &MBB : MF) { 170*81ad6265SDimitry Andric if (!MDT->isReachableFromEntry(&MBB)) 171*81ad6265SDimitry Andric continue; 172*81ad6265SDimitry Andric 173*81ad6265SDimitry Andric for (MachineBasicBlock::iterator MII = MBB.getFirstTerminator(), 174*81ad6265SDimitry Andric MIIE = MBB.end(); MII != MIIE; ++MII) { 175*81ad6265SDimitry Andric unsigned Opc = MII->getOpcode(); 176*81ad6265SDimitry Andric if (Opc == PPC::BDNZ8 || Opc == PPC::BDNZ || 177*81ad6265SDimitry Andric Opc == PPC::BDZ8 || Opc == PPC::BDZ) 178*81ad6265SDimitry Andric if (!verifyCTRBranch(&MBB, MII)) 179*81ad6265SDimitry Andric llvm_unreachable("Invalid PPC CTR loop!"); 180*81ad6265SDimitry Andric } 181*81ad6265SDimitry Andric } 182*81ad6265SDimitry Andric 183*81ad6265SDimitry Andric return false; 184*81ad6265SDimitry Andric } 185*81ad6265SDimitry Andric #endif // NDEBUG 186