brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.7 KiB · bb4178b Raw
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