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