181ad6265SDimitry Andric //===-- PPCCTRLoops.cpp - Verify CTR loops -----------------===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // This pass verifies that all bdnz/bdz instructions are dominated by a loop 1081ad6265SDimitry Andric // mtctr before any other instructions that might clobber the ctr register. 1181ad6265SDimitry Andric // 1281ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1381ad6265SDimitry Andric 1481ad6265SDimitry Andric // CTR loops are produced by the HardwareLoops pass and this pass is simply a 1581ad6265SDimitry Andric // verification that no invalid CTR loops are produced. As such, it isn't 1681ad6265SDimitry Andric // something that needs to be run (or even defined) for Release builds so the 1781ad6265SDimitry Andric // entire file is guarded by NDEBUG. 1881ad6265SDimitry Andric #ifndef NDEBUG 1981ad6265SDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h" 2081ad6265SDimitry Andric #include "PPC.h" 2181ad6265SDimitry Andric #include "llvm/ADT/SmallSet.h" 2281ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h" 2381ad6265SDimitry Andric #include "llvm/ADT/StringRef.h" 2481ad6265SDimitry Andric #include "llvm/ADT/ilist_iterator.h" 2581ad6265SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 2681ad6265SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 2781ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 2881ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 2981ad6265SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 3081ad6265SDimitry Andric #include "llvm/CodeGen/MachineInstrBundleIterator.h" 3181ad6265SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 3281ad6265SDimitry Andric #include "llvm/CodeGen/Register.h" 3381ad6265SDimitry Andric #include "llvm/InitializePasses.h" 3481ad6265SDimitry Andric #include "llvm/Pass.h" 3581ad6265SDimitry Andric #include "llvm/PassRegistry.h" 3681ad6265SDimitry Andric #include "llvm/Support/CodeGen.h" 3781ad6265SDimitry Andric #include "llvm/Support/Debug.h" 3881ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h" 3981ad6265SDimitry Andric #include "llvm/Support/GenericDomTreeConstruction.h" 4081ad6265SDimitry Andric #include "llvm/Support/Printable.h" 4181ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h" 4281ad6265SDimitry Andric 4381ad6265SDimitry Andric using namespace llvm; 4481ad6265SDimitry Andric 4581ad6265SDimitry Andric #define DEBUG_TYPE "ppc-ctrloops-verify" 4681ad6265SDimitry Andric 4781ad6265SDimitry Andric namespace { 4881ad6265SDimitry Andric 4981ad6265SDimitry Andric struct PPCCTRLoopsVerify : public MachineFunctionPass { 5081ad6265SDimitry Andric public: 5181ad6265SDimitry Andric static char ID; 5281ad6265SDimitry Andric 5381ad6265SDimitry Andric PPCCTRLoopsVerify() : MachineFunctionPass(ID) { 5481ad6265SDimitry Andric initializePPCCTRLoopsVerifyPass(*PassRegistry::getPassRegistry()); 5581ad6265SDimitry Andric } 5681ad6265SDimitry Andric 5781ad6265SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 58*0fca6ea1SDimitry Andric AU.addRequired<MachineDominatorTreeWrapperPass>(); 5981ad6265SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 6081ad6265SDimitry Andric } 6181ad6265SDimitry Andric 6281ad6265SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 6381ad6265SDimitry Andric 6481ad6265SDimitry Andric private: 6581ad6265SDimitry Andric MachineDominatorTree *MDT; 6681ad6265SDimitry Andric }; 6781ad6265SDimitry Andric 6881ad6265SDimitry Andric char PPCCTRLoopsVerify::ID = 0; 6981ad6265SDimitry Andric } // end anonymous namespace 7081ad6265SDimitry Andric 7181ad6265SDimitry Andric INITIALIZE_PASS_BEGIN(PPCCTRLoopsVerify, "ppc-ctr-loops-verify", 7281ad6265SDimitry Andric "PowerPC CTR Loops Verify", false, false) 73*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) 7481ad6265SDimitry Andric INITIALIZE_PASS_END(PPCCTRLoopsVerify, "ppc-ctr-loops-verify", 7581ad6265SDimitry Andric "PowerPC CTR Loops Verify", false, false) 7681ad6265SDimitry Andric 7781ad6265SDimitry Andric FunctionPass *llvm::createPPCCTRLoopsVerify() { 7881ad6265SDimitry Andric return new PPCCTRLoopsVerify(); 7981ad6265SDimitry Andric } 8081ad6265SDimitry Andric 8181ad6265SDimitry Andric static bool clobbersCTR(const MachineInstr &MI) { 8281ad6265SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 8381ad6265SDimitry Andric if (MO.isReg()) { 8481ad6265SDimitry Andric if (MO.isDef() && (MO.getReg() == PPC::CTR || MO.getReg() == PPC::CTR8)) 8581ad6265SDimitry Andric return true; 8681ad6265SDimitry Andric } else if (MO.isRegMask()) { 8781ad6265SDimitry Andric if (MO.clobbersPhysReg(PPC::CTR) || MO.clobbersPhysReg(PPC::CTR8)) 8881ad6265SDimitry Andric return true; 8981ad6265SDimitry Andric } 9081ad6265SDimitry Andric } 9181ad6265SDimitry Andric 9281ad6265SDimitry Andric return false; 9381ad6265SDimitry Andric } 9481ad6265SDimitry Andric 9581ad6265SDimitry Andric static bool verifyCTRBranch(MachineBasicBlock *MBB, 9681ad6265SDimitry Andric MachineBasicBlock::iterator I) { 9781ad6265SDimitry Andric MachineBasicBlock::iterator BI = I; 9881ad6265SDimitry Andric SmallSet<MachineBasicBlock *, 16> Visited; 9981ad6265SDimitry Andric SmallVector<MachineBasicBlock *, 8> Preds; 10081ad6265SDimitry Andric bool CheckPreds; 10181ad6265SDimitry Andric 10281ad6265SDimitry Andric if (I == MBB->begin()) { 10381ad6265SDimitry Andric Visited.insert(MBB); 10481ad6265SDimitry Andric goto queue_preds; 10581ad6265SDimitry Andric } else 10681ad6265SDimitry Andric --I; 10781ad6265SDimitry Andric 10881ad6265SDimitry Andric check_block: 10981ad6265SDimitry Andric Visited.insert(MBB); 11081ad6265SDimitry Andric if (I == MBB->end()) 11181ad6265SDimitry Andric goto queue_preds; 11281ad6265SDimitry Andric 11381ad6265SDimitry Andric CheckPreds = true; 11481ad6265SDimitry Andric for (MachineBasicBlock::iterator IE = MBB->begin();; --I) { 11581ad6265SDimitry Andric unsigned Opc = I->getOpcode(); 11681ad6265SDimitry Andric if (Opc == PPC::MTCTRloop || Opc == PPC::MTCTR8loop) { 11781ad6265SDimitry Andric CheckPreds = false; 11881ad6265SDimitry Andric break; 11981ad6265SDimitry Andric } 12081ad6265SDimitry Andric 12181ad6265SDimitry Andric if (I != BI && clobbersCTR(*I)) { 12281ad6265SDimitry Andric LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " (" << MBB->getFullName() 12381ad6265SDimitry Andric << ") instruction " << *I 12481ad6265SDimitry Andric << " clobbers CTR, invalidating " 12581ad6265SDimitry Andric << printMBBReference(*BI->getParent()) << " (" 12681ad6265SDimitry Andric << BI->getParent()->getFullName() << ") instruction " 12781ad6265SDimitry Andric << *BI << "\n"); 12881ad6265SDimitry Andric return false; 12981ad6265SDimitry Andric } 13081ad6265SDimitry Andric 13181ad6265SDimitry Andric if (I == IE) 13281ad6265SDimitry Andric break; 13381ad6265SDimitry Andric } 13481ad6265SDimitry Andric 13581ad6265SDimitry Andric if (!CheckPreds && Preds.empty()) 13681ad6265SDimitry Andric return true; 13781ad6265SDimitry Andric 13881ad6265SDimitry Andric if (CheckPreds) { 13981ad6265SDimitry Andric queue_preds: 14081ad6265SDimitry Andric if (MachineFunction::iterator(MBB) == MBB->getParent()->begin()) { 14181ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Unable to find a MTCTR instruction for " 14281ad6265SDimitry Andric << printMBBReference(*BI->getParent()) << " (" 14381ad6265SDimitry Andric << BI->getParent()->getFullName() << ") instruction " 14481ad6265SDimitry Andric << *BI << "\n"); 14581ad6265SDimitry Andric return false; 14681ad6265SDimitry Andric } 14781ad6265SDimitry Andric 14881ad6265SDimitry Andric append_range(Preds, MBB->predecessors()); 14981ad6265SDimitry Andric } 15081ad6265SDimitry Andric 15181ad6265SDimitry Andric do { 15281ad6265SDimitry Andric MBB = Preds.pop_back_val(); 15381ad6265SDimitry Andric if (!Visited.count(MBB)) { 15481ad6265SDimitry Andric I = MBB->getLastNonDebugInstr(); 15581ad6265SDimitry Andric goto check_block; 15681ad6265SDimitry Andric } 15781ad6265SDimitry Andric } while (!Preds.empty()); 15881ad6265SDimitry Andric 15981ad6265SDimitry Andric return true; 16081ad6265SDimitry Andric } 16181ad6265SDimitry Andric 16281ad6265SDimitry Andric bool PPCCTRLoopsVerify::runOnMachineFunction(MachineFunction &MF) { 163*0fca6ea1SDimitry Andric MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree(); 16481ad6265SDimitry Andric 16581ad6265SDimitry Andric // Verify that all bdnz/bdz instructions are dominated by a loop mtctr before 16681ad6265SDimitry Andric // any other instructions that might clobber the ctr register. 16781ad6265SDimitry Andric for (MachineBasicBlock &MBB : MF) { 16881ad6265SDimitry Andric if (!MDT->isReachableFromEntry(&MBB)) 16981ad6265SDimitry Andric continue; 17081ad6265SDimitry Andric 17181ad6265SDimitry Andric for (MachineBasicBlock::iterator MII = MBB.getFirstTerminator(), 17281ad6265SDimitry Andric MIIE = MBB.end(); MII != MIIE; ++MII) { 17381ad6265SDimitry Andric unsigned Opc = MII->getOpcode(); 17481ad6265SDimitry Andric if (Opc == PPC::BDNZ8 || Opc == PPC::BDNZ || 17581ad6265SDimitry Andric Opc == PPC::BDZ8 || Opc == PPC::BDZ) 17681ad6265SDimitry Andric if (!verifyCTRBranch(&MBB, MII)) 17781ad6265SDimitry Andric llvm_unreachable("Invalid PPC CTR loop!"); 17881ad6265SDimitry Andric } 17981ad6265SDimitry Andric } 18081ad6265SDimitry Andric 18181ad6265SDimitry Andric return false; 18281ad6265SDimitry Andric } 18381ad6265SDimitry Andric #endif // NDEBUG 184