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