199 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// A pass that form early (predicated) returns. If-conversion handles some of10// this, but this pass picks up some remaining cases.11//12//===----------------------------------------------------------------------===//13 14#include "PPC.h"15#include "PPCInstrInfo.h"16#include "llvm/ADT/STLExtras.h"17#include "llvm/ADT/Statistic.h"18#include "llvm/CodeGen/MachineFrameInfo.h"19#include "llvm/CodeGen/MachineFunctionPass.h"20#include "llvm/CodeGen/MachineInstrBuilder.h"21#include "llvm/CodeGen/MachineMemOperand.h"22#include "llvm/Support/ErrorHandling.h"23 24using namespace llvm;25 26#define DEBUG_TYPE "ppc-early-ret"27STATISTIC(NumBCLR, "Number of early conditional returns");28STATISTIC(NumBLR, "Number of early returns");29 30namespace {31 // PPCEarlyReturn pass - For simple functions without epilogue code, move32 // returns up, and create conditional returns, to avoid unnecessary33 // branch-to-blr sequences.34 struct PPCEarlyReturn : public MachineFunctionPass {35 static char ID;36 PPCEarlyReturn() : MachineFunctionPass(ID) {}37 38 const TargetInstrInfo *TII;39 40protected:41 bool processBlock(MachineBasicBlock &ReturnMBB) {42 bool Changed = false;43 44 MachineBasicBlock::iterator I = ReturnMBB.begin();45 I = ReturnMBB.SkipPHIsLabelsAndDebug(I);46 47 // The block must be essentially empty except for the blr.48 if (I == ReturnMBB.end() ||49 (I->getOpcode() != PPC::BLR && I->getOpcode() != PPC::BLR8) ||50 I != ReturnMBB.getLastNonDebugInstr())51 return Changed;52 53 SmallVector<MachineBasicBlock*, 8> PredToRemove;54 for (MachineBasicBlock *Pred : ReturnMBB.predecessors()) {55 bool OtherReference = false, BlockChanged = false;56 57 if (Pred->empty())58 continue;59 60 for (MachineBasicBlock::iterator J = Pred->getLastNonDebugInstr();;) {61 if (J == Pred->end())62 break;63 64 if (J->getOpcode() == PPC::B) {65 if (J->getOperand(0).getMBB() == &ReturnMBB) {66 // This is an unconditional branch to the return. Replace the67 // branch with a blr.68 MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I);69 Pred->insert(J, MI);70 71 MachineBasicBlock::iterator K = J--;72 K->eraseFromParent();73 BlockChanged = true;74 ++NumBLR;75 continue;76 }77 } else if (J->getOpcode() == PPC::BCC) {78 if (J->getOperand(2).getMBB() == &ReturnMBB) {79 // This is a conditional branch to the return. Replace the branch80 // with a bclr.81 MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I);82 MI->setDesc(TII->get(PPC::BCCLR));83 MachineInstrBuilder(*ReturnMBB.getParent(), MI)84 .add(J->getOperand(0))85 .add(J->getOperand(1));86 Pred->insert(J, MI);87 88 MachineBasicBlock::iterator K = J--;89 K->eraseFromParent();90 BlockChanged = true;91 ++NumBCLR;92 continue;93 }94 } else if (J->getOpcode() == PPC::BC || J->getOpcode() == PPC::BCn) {95 if (J->getOperand(1).getMBB() == &ReturnMBB) {96 // This is a conditional branch to the return. Replace the branch97 // with a bclr.98 MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I);99 MI->setDesc(100 TII->get(J->getOpcode() == PPC::BC ? PPC::BCLR : PPC::BCLRn));101 MachineInstrBuilder(*ReturnMBB.getParent(), MI)102 .add(J->getOperand(0));103 Pred->insert(J, MI);104 105 MachineBasicBlock::iterator K = J--;106 K->eraseFromParent();107 BlockChanged = true;108 ++NumBCLR;109 continue;110 }111 } else if (J->isBranch()) {112 if (J->isIndirectBranch()) {113 if (ReturnMBB.hasAddressTaken())114 OtherReference = true;115 } else116 for (unsigned i = 0; i < J->getNumOperands(); ++i)117 if (J->getOperand(i).isMBB() &&118 J->getOperand(i).getMBB() == &ReturnMBB)119 OtherReference = true;120 } else if (!J->isTerminator() && !J->isDebugInstr())121 break;122 123 if (J == Pred->begin())124 break;125 126 --J;127 }128 129 if (Pred->canFallThrough() && Pred->isLayoutSuccessor(&ReturnMBB))130 OtherReference = true;131 132 // Predecessors are stored in a vector and can't be removed here.133 if (!OtherReference && BlockChanged) {134 PredToRemove.push_back(Pred);135 }136 137 if (BlockChanged)138 Changed = true;139 }140 141 for (MachineBasicBlock *MBB : PredToRemove)142 MBB->removeSuccessor(&ReturnMBB, true);143 144 if (Changed && !ReturnMBB.hasAddressTaken()) {145 // We now might be able to merge this blr-only block into its146 // by-layout predecessor.147 if (ReturnMBB.pred_size() == 1) {148 MachineBasicBlock &PrevMBB = **ReturnMBB.pred_begin();149 if (PrevMBB.isLayoutSuccessor(&ReturnMBB) && PrevMBB.canFallThrough()) {150 // Move the blr into the preceding block.151 PrevMBB.splice(PrevMBB.end(), &ReturnMBB, I);152 PrevMBB.removeSuccessor(&ReturnMBB, true);153 }154 }155 156 if (ReturnMBB.pred_empty())157 ReturnMBB.eraseFromParent();158 }159 160 return Changed;161 }162 163public:164 bool runOnMachineFunction(MachineFunction &MF) override {165 if (skipFunction(MF.getFunction()))166 return false;167 168 TII = MF.getSubtarget().getInstrInfo();169 170 bool Changed = false;171 172 // If the function does not have at least two blocks, then there is173 // nothing to do.174 if (MF.size() < 2)175 return Changed;176 177 for (MachineBasicBlock &B : llvm::make_early_inc_range(MF))178 Changed |= processBlock(B);179 180 return Changed;181 }182 183 MachineFunctionProperties getRequiredProperties() const override {184 return MachineFunctionProperties().setNoVRegs();185 }186 187 void getAnalysisUsage(AnalysisUsage &AU) const override {188 MachineFunctionPass::getAnalysisUsage(AU);189 }190 };191}192 193INITIALIZE_PASS(PPCEarlyReturn, DEBUG_TYPE,194 "PowerPC Early-Return Creation", false, false)195 196char PPCEarlyReturn::ID = 0;197FunctionPass*198llvm::createPPCEarlyReturnPass() { return new PPCEarlyReturn(); }199