xref: /llvm-project/llvm/lib/Target/PowerPC/PPCCTRLoopsVerify.cpp (revision f71cb9dbb739bb58ce7e52e49fe384ff2ff11687)
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