19ada761bSChen Zheng //===-- PPCCTRLoops.cpp - Verify CTR loops -----------------===// 29ada761bSChen Zheng // 39ada761bSChen Zheng // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 49ada761bSChen Zheng // See https://llvm.org/LICENSE.txt for license information. 59ada761bSChen Zheng // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 69ada761bSChen Zheng // 79ada761bSChen Zheng //===----------------------------------------------------------------------===// 89ada761bSChen Zheng // 99ada761bSChen Zheng // This pass verifies that all bdnz/bdz instructions are dominated by a loop 109ada761bSChen Zheng // mtctr before any other instructions that might clobber the ctr register. 119ada761bSChen Zheng // 129ada761bSChen Zheng //===----------------------------------------------------------------------===// 139ada761bSChen Zheng 149ada761bSChen Zheng // CTR loops are produced by the HardwareLoops pass and this pass is simply a 159ada761bSChen Zheng // verification that no invalid CTR loops are produced. As such, it isn't 169ada761bSChen Zheng // something that needs to be run (or even defined) for Release builds so the 179ada761bSChen Zheng // entire file is guarded by NDEBUG. 189ada761bSChen Zheng #ifndef NDEBUG 199ada761bSChen Zheng #include "MCTargetDesc/PPCMCTargetDesc.h" 209ada761bSChen Zheng #include "PPC.h" 219ada761bSChen Zheng #include "llvm/ADT/SmallSet.h" 229ada761bSChen Zheng #include "llvm/ADT/SmallVector.h" 239ada761bSChen Zheng #include "llvm/ADT/StringRef.h" 249ada761bSChen Zheng #include "llvm/ADT/ilist_iterator.h" 259ada761bSChen Zheng #include "llvm/CodeGen/MachineBasicBlock.h" 269ada761bSChen Zheng #include "llvm/CodeGen/MachineDominators.h" 279ada761bSChen Zheng #include "llvm/CodeGen/MachineFunction.h" 289ada761bSChen Zheng #include "llvm/CodeGen/MachineFunctionPass.h" 299ada761bSChen Zheng #include "llvm/CodeGen/MachineInstr.h" 309ada761bSChen Zheng #include "llvm/CodeGen/MachineInstrBundleIterator.h" 319ada761bSChen Zheng #include "llvm/CodeGen/MachineOperand.h" 329ada761bSChen Zheng #include "llvm/CodeGen/Register.h" 339ada761bSChen Zheng #include "llvm/InitializePasses.h" 349ada761bSChen Zheng #include "llvm/Pass.h" 359ada761bSChen Zheng #include "llvm/PassRegistry.h" 369ada761bSChen Zheng #include "llvm/Support/Debug.h" 379ada761bSChen Zheng #include "llvm/Support/ErrorHandling.h" 389ada761bSChen Zheng #include "llvm/Support/Printable.h" 399ada761bSChen Zheng #include "llvm/Support/raw_ostream.h" 409ada761bSChen Zheng 419ada761bSChen Zheng using namespace llvm; 429ada761bSChen Zheng 439ada761bSChen Zheng #define DEBUG_TYPE "ppc-ctrloops-verify" 449ada761bSChen Zheng 459ada761bSChen Zheng namespace { 469ada761bSChen Zheng 479ada761bSChen Zheng struct PPCCTRLoopsVerify : public MachineFunctionPass { 489ada761bSChen Zheng public: 499ada761bSChen Zheng static char ID; 509ada761bSChen Zheng 519ada761bSChen Zheng PPCCTRLoopsVerify() : MachineFunctionPass(ID) { 529ada761bSChen Zheng initializePPCCTRLoopsVerifyPass(*PassRegistry::getPassRegistry()); 539ada761bSChen Zheng } 549ada761bSChen Zheng 559ada761bSChen Zheng void getAnalysisUsage(AnalysisUsage &AU) const override { 56*837dc542Spaperchalice AU.addRequired<MachineDominatorTreeWrapperPass>(); 579ada761bSChen Zheng MachineFunctionPass::getAnalysisUsage(AU); 589ada761bSChen Zheng } 599ada761bSChen Zheng 609ada761bSChen Zheng bool runOnMachineFunction(MachineFunction &MF) override; 619ada761bSChen Zheng 629ada761bSChen Zheng private: 639ada761bSChen Zheng MachineDominatorTree *MDT; 649ada761bSChen Zheng }; 659ada761bSChen Zheng 669ada761bSChen Zheng char PPCCTRLoopsVerify::ID = 0; 679ada761bSChen Zheng } // end anonymous namespace 689ada761bSChen Zheng 699ada761bSChen Zheng INITIALIZE_PASS_BEGIN(PPCCTRLoopsVerify, "ppc-ctr-loops-verify", 709ada761bSChen Zheng "PowerPC CTR Loops Verify", false, false) 71*837dc542Spaperchalice INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) 729ada761bSChen Zheng INITIALIZE_PASS_END(PPCCTRLoopsVerify, "ppc-ctr-loops-verify", 739ada761bSChen Zheng "PowerPC CTR Loops Verify", false, false) 749ada761bSChen Zheng 759ada761bSChen Zheng FunctionPass *llvm::createPPCCTRLoopsVerify() { 769ada761bSChen Zheng return new PPCCTRLoopsVerify(); 779ada761bSChen Zheng } 789ada761bSChen Zheng 799ada761bSChen Zheng static bool clobbersCTR(const MachineInstr &MI) { 809ada761bSChen Zheng for (const MachineOperand &MO : MI.operands()) { 819ada761bSChen Zheng if (MO.isReg()) { 829ada761bSChen Zheng if (MO.isDef() && (MO.getReg() == PPC::CTR || MO.getReg() == PPC::CTR8)) 839ada761bSChen Zheng return true; 849ada761bSChen Zheng } else if (MO.isRegMask()) { 859ada761bSChen Zheng if (MO.clobbersPhysReg(PPC::CTR) || MO.clobbersPhysReg(PPC::CTR8)) 869ada761bSChen Zheng return true; 879ada761bSChen Zheng } 889ada761bSChen Zheng } 899ada761bSChen Zheng 909ada761bSChen Zheng return false; 919ada761bSChen Zheng } 929ada761bSChen Zheng 939ada761bSChen Zheng static bool verifyCTRBranch(MachineBasicBlock *MBB, 949ada761bSChen Zheng MachineBasicBlock::iterator I) { 959ada761bSChen Zheng MachineBasicBlock::iterator BI = I; 969ada761bSChen Zheng SmallSet<MachineBasicBlock *, 16> Visited; 979ada761bSChen Zheng SmallVector<MachineBasicBlock *, 8> Preds; 989ada761bSChen Zheng bool CheckPreds; 999ada761bSChen Zheng 1009ada761bSChen Zheng if (I == MBB->begin()) { 1019ada761bSChen Zheng Visited.insert(MBB); 1029ada761bSChen Zheng goto queue_preds; 1039ada761bSChen Zheng } else 1049ada761bSChen Zheng --I; 1059ada761bSChen Zheng 1069ada761bSChen Zheng check_block: 1079ada761bSChen Zheng Visited.insert(MBB); 1089ada761bSChen Zheng if (I == MBB->end()) 1099ada761bSChen Zheng goto queue_preds; 1109ada761bSChen Zheng 1119ada761bSChen Zheng CheckPreds = true; 1129ada761bSChen Zheng for (MachineBasicBlock::iterator IE = MBB->begin();; --I) { 1139ada761bSChen Zheng unsigned Opc = I->getOpcode(); 1149ada761bSChen Zheng if (Opc == PPC::MTCTRloop || Opc == PPC::MTCTR8loop) { 1159ada761bSChen Zheng CheckPreds = false; 1169ada761bSChen Zheng break; 1179ada761bSChen Zheng } 1189ada761bSChen Zheng 1199ada761bSChen Zheng if (I != BI && clobbersCTR(*I)) { 1209ada761bSChen Zheng LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " (" << MBB->getFullName() 1219ada761bSChen Zheng << ") instruction " << *I 1229ada761bSChen Zheng << " clobbers CTR, invalidating " 1239ada761bSChen Zheng << printMBBReference(*BI->getParent()) << " (" 1249ada761bSChen Zheng << BI->getParent()->getFullName() << ") instruction " 1259ada761bSChen Zheng << *BI << "\n"); 1269ada761bSChen Zheng return false; 1279ada761bSChen Zheng } 1289ada761bSChen Zheng 1299ada761bSChen Zheng if (I == IE) 1309ada761bSChen Zheng break; 1319ada761bSChen Zheng } 1329ada761bSChen Zheng 1339ada761bSChen Zheng if (!CheckPreds && Preds.empty()) 1349ada761bSChen Zheng return true; 1359ada761bSChen Zheng 1369ada761bSChen Zheng if (CheckPreds) { 1379ada761bSChen Zheng queue_preds: 1389ada761bSChen Zheng if (MachineFunction::iterator(MBB) == MBB->getParent()->begin()) { 1399ada761bSChen Zheng LLVM_DEBUG(dbgs() << "Unable to find a MTCTR instruction for " 1409ada761bSChen Zheng << printMBBReference(*BI->getParent()) << " (" 1419ada761bSChen Zheng << BI->getParent()->getFullName() << ") instruction " 1429ada761bSChen Zheng << *BI << "\n"); 1439ada761bSChen Zheng return false; 1449ada761bSChen Zheng } 1459ada761bSChen Zheng 1469ada761bSChen Zheng append_range(Preds, MBB->predecessors()); 1479ada761bSChen Zheng } 1489ada761bSChen Zheng 1499ada761bSChen Zheng do { 1509ada761bSChen Zheng MBB = Preds.pop_back_val(); 1519ada761bSChen Zheng if (!Visited.count(MBB)) { 1529ada761bSChen Zheng I = MBB->getLastNonDebugInstr(); 1539ada761bSChen Zheng goto check_block; 1549ada761bSChen Zheng } 1559ada761bSChen Zheng } while (!Preds.empty()); 1569ada761bSChen Zheng 1579ada761bSChen Zheng return true; 1589ada761bSChen Zheng } 1599ada761bSChen Zheng 1609ada761bSChen Zheng bool PPCCTRLoopsVerify::runOnMachineFunction(MachineFunction &MF) { 161*837dc542Spaperchalice MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree(); 1629ada761bSChen Zheng 1639ada761bSChen Zheng // Verify that all bdnz/bdz instructions are dominated by a loop mtctr before 1649ada761bSChen Zheng // any other instructions that might clobber the ctr register. 1659ada761bSChen Zheng for (MachineBasicBlock &MBB : MF) { 1669ada761bSChen Zheng if (!MDT->isReachableFromEntry(&MBB)) 1679ada761bSChen Zheng continue; 1689ada761bSChen Zheng 1699ada761bSChen Zheng for (MachineBasicBlock::iterator MII = MBB.getFirstTerminator(), 1709ada761bSChen Zheng MIIE = MBB.end(); MII != MIIE; ++MII) { 1719ada761bSChen Zheng unsigned Opc = MII->getOpcode(); 1729ada761bSChen Zheng if (Opc == PPC::BDNZ8 || Opc == PPC::BDNZ || 1739ada761bSChen Zheng Opc == PPC::BDZ8 || Opc == PPC::BDZ) 1749ada761bSChen Zheng if (!verifyCTRBranch(&MBB, MII)) 1759ada761bSChen Zheng llvm_unreachable("Invalid PPC CTR loop!"); 1769ada761bSChen Zheng } 1779ada761bSChen Zheng } 1789ada761bSChen Zheng 1799ada761bSChen Zheng return false; 1809ada761bSChen Zheng } 1819ada761bSChen Zheng #endif // NDEBUG 182