Misha Brukman | 999d9cf | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 1 | //===-- PowerPCBranchSelector.cpp - Emit long conditional branches-*- C++ -*-=// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by Nate Baegeman and is distributed under the |
| 6 | // University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file contains a pass that scans a machine function to determine which |
| 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 |
| 13 | // positions pass, and a branch psuedo op to machine branch opcode pass. This |
| 14 | // pass should be run last, just before the assembly printer. |
| 15 | // |
| 16 | //===----------------------------------------------------------------------===// |
| 17 | |
| 18 | #define DEBUG_TYPE "bsel" |
| 19 | #include "PowerPC.h" |
| 20 | #include "PowerPCInstrBuilder.h" |
| 21 | #include "PowerPCInstrInfo.h" |
Misha Brukman | 363dd07 | 2004-08-17 04:58:50 +0000 | [diff] [blame] | 22 | #include "PPC32InstrInfo.h" |
Misha Brukman | 999d9cf | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 23 | #include "llvm/CodeGen/MachineFunctionPass.h" |
| 24 | #include "llvm/CodeGen/MachineFunction.h" |
| 25 | #include "Support/Debug.h" |
| 26 | #include <map> |
| 27 | using namespace llvm; |
| 28 | |
| 29 | namespace { |
| 30 | struct BSel : public MachineFunctionPass { |
| 31 | // OffsetMap - Mapping between BB and byte offset from start of function |
| 32 | std::map<MachineBasicBlock*, unsigned> OffsetMap; |
| 33 | |
| 34 | /// bytesForOpcode - A convenience function for totalling up the number of |
| 35 | /// bytes in a basic block. |
| 36 | /// |
| 37 | static unsigned bytesForOpcode(unsigned opcode) { |
| 38 | switch (opcode) { |
Misha Brukman | 5b57081 | 2004-08-10 22:47:03 +0000 | [diff] [blame] | 39 | case PPC::COND_BRANCH: |
Misha Brukman | 999d9cf | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 40 | // while this will be 4 most of the time, if we emit 12 it is just a |
| 41 | // minor pessimization that saves us from having to worry about |
| 42 | // keeping the offsets up to date later when we emit long branch glue. |
| 43 | return 12; |
Misha Brukman | 5b57081 | 2004-08-10 22:47:03 +0000 | [diff] [blame] | 44 | case PPC::MovePCtoLR: |
Misha Brukman | 999d9cf | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 45 | // MovePCtoLR is actually a combination of a branch-and-link (bl) |
| 46 | // followed by a move from link register to dest reg (mflr) |
| 47 | return 8; |
| 48 | break; |
Misha Brukman | 5b57081 | 2004-08-10 22:47:03 +0000 | [diff] [blame] | 49 | case PPC::IMPLICIT_DEF: // no asm emitted |
Misha Brukman | 999d9cf | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 50 | return 0; |
| 51 | break; |
| 52 | default: |
| 53 | return 4; // PowerPC instructions are all 4 bytes |
| 54 | break; |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | virtual bool runOnMachineFunction(MachineFunction &Fn) { |
| 59 | // Running total of instructions encountered since beginning of function |
| 60 | unsigned ByteCount = 0; |
| 61 | |
| 62 | // For each MBB, add its offset to the offset map, and count up its |
| 63 | // instructions |
| 64 | for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; |
| 65 | ++MFI) { |
| 66 | MachineBasicBlock *MBB = MFI; |
| 67 | OffsetMap[MBB] = ByteCount; |
| 68 | |
| 69 | for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end(); |
| 70 | MBBI != EE; ++MBBI) |
| 71 | ByteCount += bytesForOpcode(MBBI->getOpcode()); |
| 72 | } |
| 73 | |
| 74 | // We're about to run over the MBB's again, so reset the ByteCount |
| 75 | ByteCount = 0; |
| 76 | |
| 77 | // For each MBB, find the conditional branch pseudo instructions, and |
| 78 | // calculate the difference between the target MBB and the current ICount |
| 79 | // to decide whether or not to emit a short or long branch. |
| 80 | // |
| 81 | // short branch: |
| 82 | // bCC .L_TARGET_MBB |
| 83 | // |
| 84 | // long branch: |
| 85 | // bInverseCC $PC+8 |
| 86 | // b .L_TARGET_MBB |
| 87 | // b .L_FALLTHROUGH_MBB |
| 88 | |
| 89 | for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; |
| 90 | ++MFI) { |
| 91 | MachineBasicBlock *MBB = MFI; |
| 92 | |
| 93 | for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end(); |
| 94 | MBBI != EE; ++MBBI) { |
Misha Brukman | 5b57081 | 2004-08-10 22:47:03 +0000 | [diff] [blame] | 95 | if (MBBI->getOpcode() == PPC::COND_BRANCH) { |
Misha Brukman | 999d9cf | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 96 | // condbranch operands: |
| 97 | // 0. CR0 register |
| 98 | // 1. bc opcode |
| 99 | // 2. target MBB |
| 100 | // 3. fallthrough MBB |
| 101 | MachineBasicBlock *trueMBB = |
| 102 | MBBI->getOperand(2).getMachineBasicBlock(); |
| 103 | MachineBasicBlock *falseMBB = |
| 104 | MBBI->getOperand(3).getMachineBasicBlock(); |
| 105 | |
| 106 | int Displacement = OffsetMap[trueMBB] - ByteCount; |
| 107 | unsigned Opcode = MBBI->getOperand(1).getImmedValue(); |
Misha Brukman | 363dd07 | 2004-08-17 04:58:50 +0000 | [diff] [blame] | 108 | unsigned Inverted = PPC32InstrInfo::invertPPCBranchOpcode(Opcode); |
Misha Brukman | 999d9cf | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 109 | |
| 110 | MachineInstr *MI = MBBI; |
| 111 | if (Displacement >= -32768 && Displacement <= 32767) { |
Misha Brukman | 5b57081 | 2004-08-10 22:47:03 +0000 | [diff] [blame] | 112 | BuildMI(*MBB, MBBI, Opcode, 2).addReg(PPC::CR0).addMBB(trueMBB); |
Misha Brukman | 999d9cf | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 113 | } else { |
Misha Brukman | 5b57081 | 2004-08-10 22:47:03 +0000 | [diff] [blame] | 114 | BuildMI(*MBB, MBBI, Inverted, 2).addReg(PPC::CR0).addSImm(8); |
| 115 | BuildMI(*MBB, MBBI, PPC::B, 1).addMBB(trueMBB); |
| 116 | BuildMI(*MBB, MBBI, PPC::B, 1).addMBB(falseMBB); |
Misha Brukman | 999d9cf | 2004-07-27 18:33:06 +0000 | [diff] [blame] | 117 | } |
| 118 | MBB->erase(MI); |
| 119 | } |
| 120 | ByteCount += bytesForOpcode(MBBI->getOpcode()); |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | OffsetMap.clear(); |
| 125 | return true; |
| 126 | } |
| 127 | |
| 128 | virtual const char *getPassName() const { |
| 129 | return "PowerPC Branch Selection"; |
| 130 | } |
| 131 | }; |
| 132 | } |
| 133 | |
| 134 | /// createPPCBranchSelectionPass - returns an instance of the Branch Selection |
| 135 | /// Pass |
| 136 | /// |
| 137 | FunctionPass *llvm::createPPCBranchSelectionPass() { |
| 138 | return new BSel(); |
| 139 | } |