Home | History | Annotate | Line # | Download | only in PowerPC
      1 //===------------- PPCEarlyReturn.cpp - Form Early Returns ----------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // A pass that form early (predicated) returns. If-conversion handles some of
     10 // this, but this pass picks up some remaining cases.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "MCTargetDesc/PPCPredicates.h"
     15 #include "PPC.h"
     16 #include "PPCInstrBuilder.h"
     17 #include "PPCInstrInfo.h"
     18 #include "PPCMachineFunctionInfo.h"
     19 #include "PPCTargetMachine.h"
     20 #include "llvm/ADT/STLExtras.h"
     21 #include "llvm/ADT/Statistic.h"
     22 #include "llvm/CodeGen/MachineFrameInfo.h"
     23 #include "llvm/CodeGen/MachineFunctionPass.h"
     24 #include "llvm/CodeGen/MachineInstrBuilder.h"
     25 #include "llvm/CodeGen/MachineMemOperand.h"
     26 #include "llvm/CodeGen/MachineRegisterInfo.h"
     27 #include "llvm/MC/MCAsmInfo.h"
     28 #include "llvm/Support/Debug.h"
     29 #include "llvm/Support/ErrorHandling.h"
     30 #include "llvm/Support/TargetRegistry.h"
     31 #include "llvm/Support/raw_ostream.h"
     32 
     33 using namespace llvm;
     34 
     35 #define DEBUG_TYPE "ppc-early-ret"
     36 STATISTIC(NumBCLR, "Number of early conditional returns");
     37 STATISTIC(NumBLR,  "Number of early returns");
     38 
     39 namespace {
     40   // PPCEarlyReturn pass - For simple functions without epilogue code, move
     41   // returns up, and create conditional returns, to avoid unnecessary
     42   // branch-to-blr sequences.
     43   struct PPCEarlyReturn : public MachineFunctionPass {
     44     static char ID;
     45     PPCEarlyReturn() : MachineFunctionPass(ID) {
     46       initializePPCEarlyReturnPass(*PassRegistry::getPassRegistry());
     47     }
     48 
     49     const TargetInstrInfo *TII;
     50 
     51 protected:
     52     bool processBlock(MachineBasicBlock &ReturnMBB) {
     53       bool Changed = false;
     54 
     55       MachineBasicBlock::iterator I = ReturnMBB.begin();
     56       I = ReturnMBB.SkipPHIsLabelsAndDebug(I);
     57 
     58       // The block must be essentially empty except for the blr.
     59       if (I == ReturnMBB.end() ||
     60           (I->getOpcode() != PPC::BLR && I->getOpcode() != PPC::BLR8) ||
     61           I != ReturnMBB.getLastNonDebugInstr())
     62         return Changed;
     63 
     64       SmallVector<MachineBasicBlock*, 8> PredToRemove;
     65       for (MachineBasicBlock::pred_iterator PI = ReturnMBB.pred_begin(),
     66            PIE = ReturnMBB.pred_end(); PI != PIE; ++PI) {
     67         bool OtherReference = false, BlockChanged = false;
     68 
     69         if ((*PI)->empty())
     70           continue;
     71 
     72         for (MachineBasicBlock::iterator J = (*PI)->getLastNonDebugInstr();;) {
     73           if (J == (*PI)->end())
     74             break;
     75 
     76           if (J->getOpcode() == PPC::B) {
     77             if (J->getOperand(0).getMBB() == &ReturnMBB) {
     78               // This is an unconditional branch to the return. Replace the
     79               // branch with a blr.
     80               MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I);
     81               (*PI)->insert(J, MI);
     82 
     83               MachineBasicBlock::iterator K = J--;
     84               K->eraseFromParent();
     85               BlockChanged = true;
     86               ++NumBLR;
     87               continue;
     88             }
     89           } else if (J->getOpcode() == PPC::BCC) {
     90             if (J->getOperand(2).getMBB() == &ReturnMBB) {
     91               // This is a conditional branch to the return. Replace the branch
     92               // with a bclr.
     93               MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I);
     94               MI->setDesc(TII->get(PPC::BCCLR));
     95               MachineInstrBuilder(*ReturnMBB.getParent(), MI)
     96                   .add(J->getOperand(0))
     97                   .add(J->getOperand(1));
     98               (*PI)->insert(J, MI);
     99 
    100               MachineBasicBlock::iterator K = J--;
    101               K->eraseFromParent();
    102               BlockChanged = true;
    103               ++NumBCLR;
    104               continue;
    105             }
    106           } else if (J->getOpcode() == PPC::BC || J->getOpcode() == PPC::BCn) {
    107             if (J->getOperand(1).getMBB() == &ReturnMBB) {
    108               // This is a conditional branch to the return. Replace the branch
    109               // with a bclr.
    110               MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I);
    111               MI->setDesc(
    112                   TII->get(J->getOpcode() == PPC::BC ? PPC::BCLR : PPC::BCLRn));
    113               MachineInstrBuilder(*ReturnMBB.getParent(), MI)
    114                   .add(J->getOperand(0));
    115               (*PI)->insert(J, MI);
    116 
    117               MachineBasicBlock::iterator K = J--;
    118               K->eraseFromParent();
    119               BlockChanged = true;
    120               ++NumBCLR;
    121               continue;
    122             }
    123           } else if (J->isBranch()) {
    124             if (J->isIndirectBranch()) {
    125               if (ReturnMBB.hasAddressTaken())
    126                 OtherReference = true;
    127             } else
    128               for (unsigned i = 0; i < J->getNumOperands(); ++i)
    129                 if (J->getOperand(i).isMBB() &&
    130                     J->getOperand(i).getMBB() == &ReturnMBB)
    131                   OtherReference = true;
    132           } else if (!J->isTerminator() && !J->isDebugInstr())
    133             break;
    134 
    135           if (J == (*PI)->begin())
    136             break;
    137 
    138           --J;
    139         }
    140 
    141         if ((*PI)->canFallThrough() && (*PI)->isLayoutSuccessor(&ReturnMBB))
    142           OtherReference = true;
    143 
    144         // Predecessors are stored in a vector and can't be removed here.
    145         if (!OtherReference && BlockChanged) {
    146           PredToRemove.push_back(*PI);
    147         }
    148 
    149         if (BlockChanged)
    150           Changed = true;
    151       }
    152 
    153       for (unsigned i = 0, ie = PredToRemove.size(); i != ie; ++i)
    154         PredToRemove[i]->removeSuccessor(&ReturnMBB, true);
    155 
    156       if (Changed && !ReturnMBB.hasAddressTaken()) {
    157         // We now might be able to merge this blr-only block into its
    158         // by-layout predecessor.
    159         if (ReturnMBB.pred_size() == 1) {
    160           MachineBasicBlock &PrevMBB = **ReturnMBB.pred_begin();
    161           if (PrevMBB.isLayoutSuccessor(&ReturnMBB) && PrevMBB.canFallThrough()) {
    162             // Move the blr into the preceding block.
    163             PrevMBB.splice(PrevMBB.end(), &ReturnMBB, I);
    164             PrevMBB.removeSuccessor(&ReturnMBB, true);
    165           }
    166         }
    167 
    168         if (ReturnMBB.pred_empty())
    169           ReturnMBB.eraseFromParent();
    170       }
    171 
    172       return Changed;
    173     }
    174 
    175 public:
    176     bool runOnMachineFunction(MachineFunction &MF) override {
    177       if (skipFunction(MF.getFunction()))
    178         return false;
    179 
    180       TII = MF.getSubtarget().getInstrInfo();
    181 
    182       bool Changed = false;
    183 
    184       // If the function does not have at least two blocks, then there is
    185       // nothing to do.
    186       if (MF.size() < 2)
    187         return Changed;
    188 
    189       // We can't use a range-based for loop due to clobbering the iterator.
    190       for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E;) {
    191         MachineBasicBlock &B = *I++;
    192         Changed |= processBlock(B);
    193       }
    194 
    195       return Changed;
    196     }
    197 
    198     MachineFunctionProperties getRequiredProperties() const override {
    199       return MachineFunctionProperties().set(
    200           MachineFunctionProperties::Property::NoVRegs);
    201     }
    202 
    203     void getAnalysisUsage(AnalysisUsage &AU) const override {
    204       MachineFunctionPass::getAnalysisUsage(AU);
    205     }
    206   };
    207 }
    208 
    209 INITIALIZE_PASS(PPCEarlyReturn, DEBUG_TYPE,
    210                 "PowerPC Early-Return Creation", false, false)
    211 
    212 char PPCEarlyReturn::ID = 0;
    213 FunctionPass*
    214 llvm::createPPCEarlyReturnPass() { return new PPCEarlyReturn(); }
    215