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