| Jia Liu | b22310f | 2012-02-18 12:03:15 +0000 | [diff] [blame] | 1 | //===-- PPCBranchSelector.cpp - Emit long conditional branches ------------===// | 
| Misha Brukman | b440243 | 2005-04-21 23:30:14 +0000 | [diff] [blame] | 2 | // | 
| Misha Brukman | ef8cf02 | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
| Chris Lattner | f3ebc3f | 2007-12-29 20:36:04 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
| Misha Brukman | b440243 | 2005-04-21 23:30:14 +0000 | [diff] [blame] | 7 | // | 
| Misha Brukman | ef8cf02 | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
| Misha Brukman | b440243 | 2005-04-21 23:30:14 +0000 | [diff] [blame] | 10 | // This file contains a pass that scans a machine function to determine which | 
| Misha Brukman | ef8cf02 | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 11 | // conditional branches need more than 16 bits of displacement to reach their | 
|  | 12 | // target basic block.  It does this in two passes; a calculation of basic block | 
| Gabor Greif | 21fed66 | 2010-08-23 20:30:51 +0000 | [diff] [blame] | 13 | // positions pass, and a branch pseudo op to machine branch opcode pass.  This | 
| Misha Brukman | ef8cf02 | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 14 | // pass should be run last, just before the assembly printer. | 
|  | 15 | // | 
|  | 16 | //===----------------------------------------------------------------------===// | 
|  | 17 |  | 
| Chris Lattner | bfca1ab | 2005-10-14 23:51:18 +0000 | [diff] [blame] | 18 | #include "PPC.h" | 
| Chandler Carruth | ed0881b | 2012-12-03 16:50:05 +0000 | [diff] [blame] | 19 | #include "MCTargetDesc/PPCPredicates.h" | 
| Chris Lattner | e80bf1b | 2005-10-14 23:45:43 +0000 | [diff] [blame] | 20 | #include "PPCInstrBuilder.h" | 
| Chris Lattner | 6f3b954 | 2005-10-14 23:59:06 +0000 | [diff] [blame] | 21 | #include "PPCInstrInfo.h" | 
| Chris Lattner | 96d7386 | 2006-11-16 18:13:49 +0000 | [diff] [blame] | 22 | #include "llvm/ADT/Statistic.h" | 
| Chandler Carruth | ed0881b | 2012-12-03 16:50:05 +0000 | [diff] [blame] | 23 | #include "llvm/CodeGen/MachineFunctionPass.h" | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 24 | #include "llvm/Support/MathExtras.h" | 
| Chandler Carruth | ed0881b | 2012-12-03 16:50:05 +0000 | [diff] [blame] | 25 | #include "llvm/Target/TargetMachine.h" | 
| Eric Christopher | d913448 | 2014-08-04 21:25:23 +0000 | [diff] [blame] | 26 | #include "llvm/Target/TargetSubtargetInfo.h" | 
| Misha Brukman | ef8cf02 | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 27 | using namespace llvm; | 
|  | 28 |  | 
| Chandler Carruth | 84e68b2 | 2014-04-22 02:41:26 +0000 | [diff] [blame] | 29 | #define DEBUG_TYPE "ppc-branch-select" | 
|  | 30 |  | 
| Chris Lattner | 1ef9cd4 | 2006-12-19 22:59:26 +0000 | [diff] [blame] | 31 | STATISTIC(NumExpanded, "Number of branches expanded to long format"); | 
| Chris Lattner | 96d7386 | 2006-11-16 18:13:49 +0000 | [diff] [blame] | 32 |  | 
| Krzysztof Parzyszek | 2680b53 | 2013-02-13 17:40:07 +0000 | [diff] [blame] | 33 | namespace llvm { | 
|  | 34 | void initializePPCBSelPass(PassRegistry&); | 
|  | 35 | } | 
|  | 36 |  | 
| Misha Brukman | ef8cf02 | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 37 | namespace { | 
| Nick Lewycky | 02d5f77 | 2009-10-25 06:33:48 +0000 | [diff] [blame] | 38 | struct PPCBSel : public MachineFunctionPass { | 
| Devang Patel | 8c78a0b | 2007-05-03 01:11:54 +0000 | [diff] [blame] | 39 | static char ID; | 
| Krzysztof Parzyszek | 2680b53 | 2013-02-13 17:40:07 +0000 | [diff] [blame] | 40 | PPCBSel() : MachineFunctionPass(ID) { | 
|  | 41 | initializePPCBSelPass(*PassRegistry::getPassRegistry()); | 
|  | 42 | } | 
| Devang Patel | 09f162c | 2007-05-01 21:15:47 +0000 | [diff] [blame] | 43 |  | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 44 | /// BlockSizes - The sizes of the basic blocks in the function. | 
|  | 45 | std::vector<unsigned> BlockSizes; | 
| Misha Brukman | ef8cf02 | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 46 |  | 
| Craig Topper | 0d3fa92 | 2014-04-29 07:57:37 +0000 | [diff] [blame] | 47 | bool runOnMachineFunction(MachineFunction &Fn) override; | 
| Misha Brukman | ef8cf02 | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 48 |  | 
| Derek Schuff | 1dbf7a5 | 2016-04-04 17:09:25 +0000 | [diff] [blame] | 49 | MachineFunctionProperties getRequiredProperties() const override { | 
|  | 50 | return MachineFunctionProperties().set( | 
|  | 51 | MachineFunctionProperties::Property::AllVRegsAllocated); | 
|  | 52 | } | 
|  | 53 |  | 
| Craig Topper | 0d3fa92 | 2014-04-29 07:57:37 +0000 | [diff] [blame] | 54 | const char *getPassName() const override { | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 55 | return "PowerPC Branch Selector"; | 
| Misha Brukman | ef8cf02 | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 56 | } | 
|  | 57 | }; | 
| Devang Patel | 8c78a0b | 2007-05-03 01:11:54 +0000 | [diff] [blame] | 58 | char PPCBSel::ID = 0; | 
| Alexander Kornienko | f00654e | 2015-06-23 09:49:53 +0000 | [diff] [blame] | 59 | } | 
| Misha Brukman | ef8cf02 | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 60 |  | 
| Krzysztof Parzyszek | 2680b53 | 2013-02-13 17:40:07 +0000 | [diff] [blame] | 61 | INITIALIZE_PASS(PPCBSel, "ppc-branch-select", "PowerPC Branch Selector", | 
|  | 62 | false, false) | 
|  | 63 |  | 
| Misha Brukman | ef8cf02 | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 64 | /// createPPCBranchSelectionPass - returns an instance of the Branch Selection | 
|  | 65 | /// Pass | 
|  | 66 | /// | 
|  | 67 | FunctionPass *llvm::createPPCBranchSelectionPass() { | 
| Chris Lattner | 26e385a | 2006-02-08 19:33:26 +0000 | [diff] [blame] | 68 | return new PPCBSel(); | 
| Misha Brukman | ef8cf02 | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 69 | } | 
| Chris Lattner | 26e385a | 2006-02-08 19:33:26 +0000 | [diff] [blame] | 70 |  | 
| Chris Lattner | 26e385a | 2006-02-08 19:33:26 +0000 | [diff] [blame] | 71 | bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) { | 
| Eric Christopher | fc6de42 | 2014-08-05 02:39:49 +0000 | [diff] [blame] | 72 | const PPCInstrInfo *TII = | 
|  | 73 | static_cast<const PPCInstrInfo *>(Fn.getSubtarget().getInstrInfo()); | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 74 | // Give the blocks of the function a dense, in-order, numbering. | 
|  | 75 | Fn.RenumberBlocks(); | 
|  | 76 | BlockSizes.resize(Fn.getNumBlockIDs()); | 
|  | 77 |  | 
| Hal Finkel | d73bfba | 2015-01-03 14:58:25 +0000 | [diff] [blame] | 78 | auto GetAlignmentAdjustment = | 
|  | 79 | [TII](MachineBasicBlock &MBB, unsigned Offset) -> unsigned { | 
|  | 80 | unsigned Align = MBB.getAlignment(); | 
|  | 81 | if (!Align) | 
|  | 82 | return 0; | 
|  | 83 |  | 
|  | 84 | unsigned AlignAmt = 1 << Align; | 
|  | 85 | unsigned ParentAlign = MBB.getParent()->getAlignment(); | 
|  | 86 |  | 
|  | 87 | if (Align <= ParentAlign) | 
|  | 88 | return OffsetToAlignment(Offset, AlignAmt); | 
|  | 89 |  | 
|  | 90 | // The alignment of this MBB is larger than the function's alignment, so we | 
|  | 91 | // can't tell whether or not it will insert nops. Assume that it will. | 
|  | 92 | return AlignAmt + OffsetToAlignment(Offset, AlignAmt); | 
|  | 93 | }; | 
|  | 94 |  | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 95 | // Measure each MBB and compute a size for the entire function. | 
|  | 96 | unsigned FuncSize = 0; | 
| Chris Lattner | 26e385a | 2006-02-08 19:33:26 +0000 | [diff] [blame] | 97 | for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; | 
|  | 98 | ++MFI) { | 
| Duncan P. N. Exon Smith | ac65b4c | 2015-10-20 01:07:37 +0000 | [diff] [blame] | 99 | MachineBasicBlock *MBB = &*MFI; | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 100 |  | 
| Hal Finkel | d73bfba | 2015-01-03 14:58:25 +0000 | [diff] [blame] | 101 | // The end of the previous block may have extra nops if this block has an | 
|  | 102 | // alignment requirement. | 
|  | 103 | if (MBB->getNumber() > 0) { | 
|  | 104 | unsigned AlignExtra = GetAlignmentAdjustment(*MBB, FuncSize); | 
|  | 105 | BlockSizes[MBB->getNumber()-1] += AlignExtra; | 
|  | 106 | FuncSize += AlignExtra; | 
|  | 107 | } | 
|  | 108 |  | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 109 | unsigned BlockSize = 0; | 
| Chris Lattner | 26e385a | 2006-02-08 19:33:26 +0000 | [diff] [blame] | 110 | for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end(); | 
|  | 111 | MBBI != EE; ++MBBI) | 
| Nicolas Geoffray | ae84bbd | 2008-04-16 20:10:13 +0000 | [diff] [blame] | 112 | BlockSize += TII->GetInstSizeInBytes(MBBI); | 
| Chris Lattner | 26e385a | 2006-02-08 19:33:26 +0000 | [diff] [blame] | 113 |  | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 114 | BlockSizes[MBB->getNumber()] = BlockSize; | 
|  | 115 | FuncSize += BlockSize; | 
| Chris Lattner | 26e385a | 2006-02-08 19:33:26 +0000 | [diff] [blame] | 116 | } | 
|  | 117 |  | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 118 | // If the entire function is smaller than the displacement of a branch field, | 
|  | 119 | // we know we don't need to shrink any branches in this function.  This is a | 
|  | 120 | // common case. | 
|  | 121 | if (FuncSize < (1 << 15)) { | 
|  | 122 | BlockSizes.clear(); | 
|  | 123 | return false; | 
|  | 124 | } | 
|  | 125 |  | 
|  | 126 | // For each conditional branch, if the offset to its destination is larger | 
|  | 127 | // than the offset field allows, transform it into a long branch sequence | 
|  | 128 | // like this: | 
|  | 129 | //   short branch: | 
|  | 130 | //     bCC MBB | 
|  | 131 | //   long branch: | 
|  | 132 | //     b!CC $PC+8 | 
|  | 133 | //     b MBB | 
|  | 134 | // | 
|  | 135 | bool MadeChange = true; | 
|  | 136 | bool EverMadeChange = false; | 
|  | 137 | while (MadeChange) { | 
|  | 138 | // Iteratively expand branches until we reach a fixed point. | 
|  | 139 | MadeChange = false; | 
|  | 140 |  | 
|  | 141 | for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; | 
|  | 142 | ++MFI) { | 
|  | 143 | MachineBasicBlock &MBB = *MFI; | 
|  | 144 | unsigned MBBStartOffset = 0; | 
|  | 145 | for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); | 
|  | 146 | I != E; ++I) { | 
| Craig Topper | 062a2ba | 2014-04-25 05:30:21 +0000 | [diff] [blame] | 147 | MachineBasicBlock *Dest = nullptr; | 
| Hal Finkel | c521129 | 2013-05-21 14:21:09 +0000 | [diff] [blame] | 148 | if (I->getOpcode() == PPC::BCC && !I->getOperand(2).isImm()) | 
|  | 149 | Dest = I->getOperand(2).getMBB(); | 
| Hal Finkel | 940ab93 | 2014-02-28 00:27:01 +0000 | [diff] [blame] | 150 | else if ((I->getOpcode() == PPC::BC || I->getOpcode() == PPC::BCn) && | 
|  | 151 | !I->getOperand(1).isImm()) | 
|  | 152 | Dest = I->getOperand(1).getMBB(); | 
| Hal Finkel | c521129 | 2013-05-21 14:21:09 +0000 | [diff] [blame] | 153 | else if ((I->getOpcode() == PPC::BDNZ8 || I->getOpcode() == PPC::BDNZ || | 
|  | 154 | I->getOpcode() == PPC::BDZ8  || I->getOpcode() == PPC::BDZ) && | 
|  | 155 | !I->getOperand(0).isImm()) | 
|  | 156 | Dest = I->getOperand(0).getMBB(); | 
|  | 157 |  | 
|  | 158 | if (!Dest) { | 
| Nicolas Geoffray | ae84bbd | 2008-04-16 20:10:13 +0000 | [diff] [blame] | 159 | MBBStartOffset += TII->GetInstSizeInBytes(I); | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 160 | continue; | 
|  | 161 | } | 
|  | 162 |  | 
|  | 163 | // Determine the offset from the current branch to the destination | 
|  | 164 | // block. | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 165 | int BranchSize; | 
|  | 166 | if (Dest->getNumber() <= MBB.getNumber()) { | 
|  | 167 | // If this is a backwards branch, the delta is the offset from the | 
|  | 168 | // start of this block to this branch, plus the sizes of all blocks | 
|  | 169 | // from this block to the dest. | 
|  | 170 | BranchSize = MBBStartOffset; | 
|  | 171 |  | 
|  | 172 | for (unsigned i = Dest->getNumber(), e = MBB.getNumber(); i != e; ++i) | 
|  | 173 | BranchSize += BlockSizes[i]; | 
|  | 174 | } else { | 
|  | 175 | // Otherwise, add the size of the blocks between this block and the | 
|  | 176 | // dest to the number of bytes left in this block. | 
|  | 177 | BranchSize = -MBBStartOffset; | 
|  | 178 |  | 
|  | 179 | for (unsigned i = MBB.getNumber(), e = Dest->getNumber(); i != e; ++i) | 
|  | 180 | BranchSize += BlockSizes[i]; | 
|  | 181 | } | 
|  | 182 |  | 
|  | 183 | // If this branch is in range, ignore it. | 
| Benjamin Kramer | 2788f79 | 2010-03-29 21:13:41 +0000 | [diff] [blame] | 184 | if (isInt<16>(BranchSize)) { | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 185 | MBBStartOffset += 4; | 
|  | 186 | continue; | 
|  | 187 | } | 
| Hal Finkel | 96c2d4d | 2012-06-08 15:38:21 +0000 | [diff] [blame] | 188 |  | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 189 | // Otherwise, we have to expand it to a long branch. | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 190 | MachineInstr *OldBranch = I; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 191 | DebugLoc dl = OldBranch->getDebugLoc(); | 
| Hal Finkel | 96c2d4d | 2012-06-08 15:38:21 +0000 | [diff] [blame] | 192 |  | 
|  | 193 | if (I->getOpcode() == PPC::BCC) { | 
|  | 194 | // The BCC operands are: | 
|  | 195 | // 0. PPC branch predicate | 
|  | 196 | // 1. CR register | 
|  | 197 | // 2. Target MBB | 
|  | 198 | PPC::Predicate Pred = (PPC::Predicate)I->getOperand(0).getImm(); | 
|  | 199 | unsigned CRReg = I->getOperand(1).getReg(); | 
|  | 200 |  | 
|  | 201 | // Jump over the uncond branch inst (i.e. $PC+8) on opposite condition. | 
|  | 202 | BuildMI(MBB, I, dl, TII->get(PPC::BCC)) | 
|  | 203 | .addImm(PPC::InvertPredicate(Pred)).addReg(CRReg).addImm(2); | 
| Hal Finkel | 940ab93 | 2014-02-28 00:27:01 +0000 | [diff] [blame] | 204 | } else if (I->getOpcode() == PPC::BC) { | 
|  | 205 | unsigned CRBit = I->getOperand(0).getReg(); | 
|  | 206 | BuildMI(MBB, I, dl, TII->get(PPC::BCn)).addReg(CRBit).addImm(2); | 
|  | 207 | } else if (I->getOpcode() == PPC::BCn) { | 
|  | 208 | unsigned CRBit = I->getOperand(0).getReg(); | 
|  | 209 | BuildMI(MBB, I, dl, TII->get(PPC::BC)).addReg(CRBit).addImm(2); | 
| Hal Finkel | 96c2d4d | 2012-06-08 15:38:21 +0000 | [diff] [blame] | 210 | } else if (I->getOpcode() == PPC::BDNZ) { | 
|  | 211 | BuildMI(MBB, I, dl, TII->get(PPC::BDZ)).addImm(2); | 
|  | 212 | } else if (I->getOpcode() == PPC::BDNZ8) { | 
|  | 213 | BuildMI(MBB, I, dl, TII->get(PPC::BDZ8)).addImm(2); | 
|  | 214 | } else if (I->getOpcode() == PPC::BDZ) { | 
|  | 215 | BuildMI(MBB, I, dl, TII->get(PPC::BDNZ)).addImm(2); | 
|  | 216 | } else if (I->getOpcode() == PPC::BDZ8) { | 
|  | 217 | BuildMI(MBB, I, dl, TII->get(PPC::BDNZ8)).addImm(2); | 
|  | 218 | } else { | 
|  | 219 | llvm_unreachable("Unhandled branch type!"); | 
|  | 220 | } | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 221 |  | 
|  | 222 | // Uncond branch to the real destination. | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 223 | I = BuildMI(MBB, I, dl, TII->get(PPC::B)).addMBB(Dest); | 
| Chris Lattner | 542dfd5 | 2006-11-18 00:32:03 +0000 | [diff] [blame] | 224 |  | 
|  | 225 | // Remove the old branch from the function. | 
|  | 226 | OldBranch->eraseFromParent(); | 
|  | 227 |  | 
|  | 228 | // Remember that this instruction is 8-bytes, increase the size of the | 
|  | 229 | // block by 4, remember to iterate. | 
|  | 230 | BlockSizes[MBB.getNumber()] += 4; | 
|  | 231 | MBBStartOffset += 8; | 
|  | 232 | ++NumExpanded; | 
|  | 233 | MadeChange = true; | 
|  | 234 | } | 
|  | 235 | } | 
|  | 236 | EverMadeChange |= MadeChange; | 
|  | 237 | } | 
|  | 238 |  | 
|  | 239 | BlockSizes.clear(); | 
| Chris Lattner | 26e385a | 2006-02-08 19:33:26 +0000 | [diff] [blame] | 240 | return true; | 
|  | 241 | } |