109467b48Spatrick //===-- SystemZLongBranch.cpp - Branch lengthening for SystemZ ------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This pass makes sure that all branches are in range. There are several ways
1009467b48Spatrick // in which this could be done. One aggressive approach is to assume that all
1109467b48Spatrick // branches are in range and successively replace those that turn out not
1209467b48Spatrick // to be in range with a longer form (branch relaxation). A simple
1309467b48Spatrick // implementation is to continually walk through the function relaxing
1409467b48Spatrick // branches until no more changes are needed and a fixed point is reached.
1509467b48Spatrick // However, in the pathological worst case, this implementation is
1609467b48Spatrick // quadratic in the number of blocks; relaxing branch N can make branch N-1
1709467b48Spatrick // go out of range, which in turn can make branch N-2 go out of range,
1809467b48Spatrick // and so on.
1909467b48Spatrick //
2009467b48Spatrick // An alternative approach is to assume that all branches must be
2109467b48Spatrick // converted to their long forms, then reinstate the short forms of
2209467b48Spatrick // branches that, even under this pessimistic assumption, turn out to be
2309467b48Spatrick // in range (branch shortening). This too can be implemented as a function
2409467b48Spatrick // walk that is repeated until a fixed point is reached. In general,
2509467b48Spatrick // the result of shortening is not as good as that of relaxation, and
2609467b48Spatrick // shortening is also quadratic in the worst case; shortening branch N
2709467b48Spatrick // can bring branch N-1 in range of the short form, which in turn can do
2809467b48Spatrick // the same for branch N-2, and so on. The main advantage of shortening
2909467b48Spatrick // is that each walk through the function produces valid code, so it is
3009467b48Spatrick // possible to stop at any point after the first walk. The quadraticness
3109467b48Spatrick // could therefore be handled with a maximum pass count, although the
3209467b48Spatrick // question then becomes: what maximum count should be used?
3309467b48Spatrick //
3409467b48Spatrick // On SystemZ, long branches are only needed for functions bigger than 64k,
3509467b48Spatrick // which are relatively rare to begin with, and the long branch sequences
3609467b48Spatrick // are actually relatively cheap. It therefore doesn't seem worth spending
3709467b48Spatrick // much compilation time on the problem. Instead, the approach we take is:
3809467b48Spatrick //
3909467b48Spatrick // (1) Work out the address that each block would have if no branches
4009467b48Spatrick // need relaxing. Exit the pass early if all branches are in range
4109467b48Spatrick // according to this assumption.
4209467b48Spatrick //
4309467b48Spatrick // (2) Work out the address that each block would have if all branches
4409467b48Spatrick // need relaxing.
4509467b48Spatrick //
4609467b48Spatrick // (3) Walk through the block calculating the final address of each instruction
4709467b48Spatrick // and relaxing those that need to be relaxed. For backward branches,
4809467b48Spatrick // this check uses the final address of the target block, as calculated
4909467b48Spatrick // earlier in the walk. For forward branches, this check uses the
5009467b48Spatrick // address of the target block that was calculated in (2). Both checks
5109467b48Spatrick // give a conservatively-correct range.
5209467b48Spatrick //
5309467b48Spatrick //===----------------------------------------------------------------------===//
5409467b48Spatrick
5509467b48Spatrick #include "SystemZ.h"
5609467b48Spatrick #include "SystemZInstrInfo.h"
5709467b48Spatrick #include "SystemZTargetMachine.h"
5809467b48Spatrick #include "llvm/ADT/SmallVector.h"
5909467b48Spatrick #include "llvm/ADT/Statistic.h"
6009467b48Spatrick #include "llvm/ADT/StringRef.h"
6109467b48Spatrick #include "llvm/CodeGen/MachineBasicBlock.h"
6209467b48Spatrick #include "llvm/CodeGen/MachineFunction.h"
6309467b48Spatrick #include "llvm/CodeGen/MachineFunctionPass.h"
6409467b48Spatrick #include "llvm/CodeGen/MachineInstr.h"
6509467b48Spatrick #include "llvm/CodeGen/MachineInstrBuilder.h"
6609467b48Spatrick #include "llvm/IR/DebugLoc.h"
6709467b48Spatrick #include "llvm/Support/ErrorHandling.h"
6809467b48Spatrick #include <cassert>
6909467b48Spatrick #include <cstdint>
7009467b48Spatrick
7109467b48Spatrick using namespace llvm;
7209467b48Spatrick
7309467b48Spatrick #define DEBUG_TYPE "systemz-long-branch"
7409467b48Spatrick
7509467b48Spatrick STATISTIC(LongBranches, "Number of long branches.");
7609467b48Spatrick
7709467b48Spatrick namespace {
7809467b48Spatrick
7909467b48Spatrick // Represents positional information about a basic block.
8009467b48Spatrick struct MBBInfo {
8109467b48Spatrick // The address that we currently assume the block has.
8209467b48Spatrick uint64_t Address = 0;
8309467b48Spatrick
8409467b48Spatrick // The size of the block in bytes, excluding terminators.
8509467b48Spatrick // This value never changes.
8609467b48Spatrick uint64_t Size = 0;
8709467b48Spatrick
8809467b48Spatrick // The minimum alignment of the block.
8909467b48Spatrick // This value never changes.
9009467b48Spatrick Align Alignment;
9109467b48Spatrick
9209467b48Spatrick // The number of terminators in this block. This value never changes.
9309467b48Spatrick unsigned NumTerminators = 0;
9409467b48Spatrick
9509467b48Spatrick MBBInfo() = default;
9609467b48Spatrick };
9709467b48Spatrick
9809467b48Spatrick // Represents the state of a block terminator.
9909467b48Spatrick struct TerminatorInfo {
10009467b48Spatrick // If this terminator is a relaxable branch, this points to the branch
10109467b48Spatrick // instruction, otherwise it is null.
10209467b48Spatrick MachineInstr *Branch = nullptr;
10309467b48Spatrick
10409467b48Spatrick // The address that we currently assume the terminator has.
10509467b48Spatrick uint64_t Address = 0;
10609467b48Spatrick
10709467b48Spatrick // The current size of the terminator in bytes.
10809467b48Spatrick uint64_t Size = 0;
10909467b48Spatrick
11009467b48Spatrick // If Branch is nonnull, this is the number of the target block,
11109467b48Spatrick // otherwise it is unused.
11209467b48Spatrick unsigned TargetBlock = 0;
11309467b48Spatrick
11409467b48Spatrick // If Branch is nonnull, this is the length of the longest relaxed form,
11509467b48Spatrick // otherwise it is zero.
11609467b48Spatrick unsigned ExtraRelaxSize = 0;
11709467b48Spatrick
11809467b48Spatrick TerminatorInfo() = default;
11909467b48Spatrick };
12009467b48Spatrick
12109467b48Spatrick // Used to keep track of the current position while iterating over the blocks.
12209467b48Spatrick struct BlockPosition {
12309467b48Spatrick // The address that we assume this position has.
12409467b48Spatrick uint64_t Address = 0;
12509467b48Spatrick
12609467b48Spatrick // The number of low bits in Address that are known to be the same
12709467b48Spatrick // as the runtime address.
12809467b48Spatrick unsigned KnownBits;
12909467b48Spatrick
BlockPosition__anon3e50f6080111::BlockPosition13009467b48Spatrick BlockPosition(unsigned InitialLogAlignment)
13109467b48Spatrick : KnownBits(InitialLogAlignment) {}
13209467b48Spatrick };
13309467b48Spatrick
13409467b48Spatrick class SystemZLongBranch : public MachineFunctionPass {
13509467b48Spatrick public:
13609467b48Spatrick static char ID;
13709467b48Spatrick
SystemZLongBranch()138*d415bd75Srobert SystemZLongBranch() : MachineFunctionPass(ID) {
139*d415bd75Srobert initializeSystemZLongBranchPass(*PassRegistry::getPassRegistry());
140*d415bd75Srobert }
14109467b48Spatrick
14209467b48Spatrick bool runOnMachineFunction(MachineFunction &F) override;
14309467b48Spatrick
getRequiredProperties() const14409467b48Spatrick MachineFunctionProperties getRequiredProperties() const override {
14509467b48Spatrick return MachineFunctionProperties().set(
14609467b48Spatrick MachineFunctionProperties::Property::NoVRegs);
14709467b48Spatrick }
14809467b48Spatrick
14909467b48Spatrick private:
15009467b48Spatrick void skipNonTerminators(BlockPosition &Position, MBBInfo &Block);
15109467b48Spatrick void skipTerminator(BlockPosition &Position, TerminatorInfo &Terminator,
15209467b48Spatrick bool AssumeRelaxed);
15309467b48Spatrick TerminatorInfo describeTerminator(MachineInstr &MI);
15409467b48Spatrick uint64_t initMBBInfo();
15509467b48Spatrick bool mustRelaxBranch(const TerminatorInfo &Terminator, uint64_t Address);
15609467b48Spatrick bool mustRelaxABranch();
15709467b48Spatrick void setWorstCaseAddresses();
15809467b48Spatrick void splitBranchOnCount(MachineInstr *MI, unsigned AddOpcode);
15909467b48Spatrick void splitCompareBranch(MachineInstr *MI, unsigned CompareOpcode);
16009467b48Spatrick void relaxBranch(TerminatorInfo &Terminator);
16109467b48Spatrick void relaxBranches();
16209467b48Spatrick
16309467b48Spatrick const SystemZInstrInfo *TII = nullptr;
16409467b48Spatrick MachineFunction *MF = nullptr;
16509467b48Spatrick SmallVector<MBBInfo, 16> MBBs;
16609467b48Spatrick SmallVector<TerminatorInfo, 16> Terminators;
16709467b48Spatrick };
16809467b48Spatrick
16909467b48Spatrick char SystemZLongBranch::ID = 0;
17009467b48Spatrick
17109467b48Spatrick const uint64_t MaxBackwardRange = 0x10000;
17209467b48Spatrick const uint64_t MaxForwardRange = 0xfffe;
17309467b48Spatrick
17409467b48Spatrick } // end anonymous namespace
17509467b48Spatrick
176*d415bd75Srobert INITIALIZE_PASS(SystemZLongBranch, DEBUG_TYPE, "SystemZ Long Branch", false,
177*d415bd75Srobert false)
178*d415bd75Srobert
17909467b48Spatrick // Position describes the state immediately before Block. Update Block
18009467b48Spatrick // accordingly and move Position to the end of the block's non-terminator
18109467b48Spatrick // instructions.
skipNonTerminators(BlockPosition & Position,MBBInfo & Block)18209467b48Spatrick void SystemZLongBranch::skipNonTerminators(BlockPosition &Position,
18309467b48Spatrick MBBInfo &Block) {
18409467b48Spatrick if (Log2(Block.Alignment) > Position.KnownBits) {
18509467b48Spatrick // When calculating the address of Block, we need to conservatively
18609467b48Spatrick // assume that Block had the worst possible misalignment.
18709467b48Spatrick Position.Address +=
18809467b48Spatrick (Block.Alignment.value() - (uint64_t(1) << Position.KnownBits));
18909467b48Spatrick Position.KnownBits = Log2(Block.Alignment);
19009467b48Spatrick }
19109467b48Spatrick
19209467b48Spatrick // Align the addresses.
19309467b48Spatrick Position.Address = alignTo(Position.Address, Block.Alignment);
19409467b48Spatrick
19509467b48Spatrick // Record the block's position.
19609467b48Spatrick Block.Address = Position.Address;
19709467b48Spatrick
19809467b48Spatrick // Move past the non-terminators in the block.
19909467b48Spatrick Position.Address += Block.Size;
20009467b48Spatrick }
20109467b48Spatrick
20209467b48Spatrick // Position describes the state immediately before Terminator.
20309467b48Spatrick // Update Terminator accordingly and move Position past it.
20409467b48Spatrick // Assume that Terminator will be relaxed if AssumeRelaxed.
skipTerminator(BlockPosition & Position,TerminatorInfo & Terminator,bool AssumeRelaxed)20509467b48Spatrick void SystemZLongBranch::skipTerminator(BlockPosition &Position,
20609467b48Spatrick TerminatorInfo &Terminator,
20709467b48Spatrick bool AssumeRelaxed) {
20809467b48Spatrick Terminator.Address = Position.Address;
20909467b48Spatrick Position.Address += Terminator.Size;
21009467b48Spatrick if (AssumeRelaxed)
21109467b48Spatrick Position.Address += Terminator.ExtraRelaxSize;
21209467b48Spatrick }
21309467b48Spatrick
getInstSizeInBytes(const MachineInstr & MI,const SystemZInstrInfo * TII)214*d415bd75Srobert static unsigned getInstSizeInBytes(const MachineInstr &MI,
215*d415bd75Srobert const SystemZInstrInfo *TII) {
216*d415bd75Srobert unsigned Size = TII->getInstSizeInBytes(MI);
217*d415bd75Srobert assert((Size ||
218*d415bd75Srobert // These do not have a size:
219*d415bd75Srobert MI.isDebugOrPseudoInstr() || MI.isPosition() || MI.isKill() ||
220*d415bd75Srobert MI.isImplicitDef() || MI.getOpcode() == TargetOpcode::MEMBARRIER ||
221*d415bd75Srobert // These have a size that may be zero:
222*d415bd75Srobert MI.isInlineAsm() || MI.getOpcode() == SystemZ::STACKMAP ||
223*d415bd75Srobert MI.getOpcode() == SystemZ::PATCHPOINT) &&
224*d415bd75Srobert "Missing size value for instruction.");
225*d415bd75Srobert return Size;
226*d415bd75Srobert }
227*d415bd75Srobert
22809467b48Spatrick // Return a description of terminator instruction MI.
describeTerminator(MachineInstr & MI)22909467b48Spatrick TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr &MI) {
23009467b48Spatrick TerminatorInfo Terminator;
231*d415bd75Srobert Terminator.Size = getInstSizeInBytes(MI, TII);
23209467b48Spatrick if (MI.isConditionalBranch() || MI.isUnconditionalBranch()) {
23309467b48Spatrick switch (MI.getOpcode()) {
23409467b48Spatrick case SystemZ::J:
23509467b48Spatrick // Relaxes to JG, which is 2 bytes longer.
23609467b48Spatrick Terminator.ExtraRelaxSize = 2;
23709467b48Spatrick break;
23809467b48Spatrick case SystemZ::BRC:
23909467b48Spatrick // Relaxes to BRCL, which is 2 bytes longer.
24009467b48Spatrick Terminator.ExtraRelaxSize = 2;
24109467b48Spatrick break;
24209467b48Spatrick case SystemZ::BRCT:
24309467b48Spatrick case SystemZ::BRCTG:
24409467b48Spatrick // Relaxes to A(G)HI and BRCL, which is 6 bytes longer.
24509467b48Spatrick Terminator.ExtraRelaxSize = 6;
24609467b48Spatrick break;
24709467b48Spatrick case SystemZ::BRCTH:
24809467b48Spatrick // Never needs to be relaxed.
24909467b48Spatrick Terminator.ExtraRelaxSize = 0;
25009467b48Spatrick break;
25109467b48Spatrick case SystemZ::CRJ:
25209467b48Spatrick case SystemZ::CLRJ:
25309467b48Spatrick // Relaxes to a C(L)R/BRCL sequence, which is 2 bytes longer.
25409467b48Spatrick Terminator.ExtraRelaxSize = 2;
25509467b48Spatrick break;
25609467b48Spatrick case SystemZ::CGRJ:
25709467b48Spatrick case SystemZ::CLGRJ:
25809467b48Spatrick // Relaxes to a C(L)GR/BRCL sequence, which is 4 bytes longer.
25909467b48Spatrick Terminator.ExtraRelaxSize = 4;
26009467b48Spatrick break;
26109467b48Spatrick case SystemZ::CIJ:
26209467b48Spatrick case SystemZ::CGIJ:
26309467b48Spatrick // Relaxes to a C(G)HI/BRCL sequence, which is 4 bytes longer.
26409467b48Spatrick Terminator.ExtraRelaxSize = 4;
26509467b48Spatrick break;
26609467b48Spatrick case SystemZ::CLIJ:
26709467b48Spatrick case SystemZ::CLGIJ:
26809467b48Spatrick // Relaxes to a CL(G)FI/BRCL sequence, which is 6 bytes longer.
26909467b48Spatrick Terminator.ExtraRelaxSize = 6;
27009467b48Spatrick break;
27109467b48Spatrick default:
27209467b48Spatrick llvm_unreachable("Unrecognized branch instruction");
27309467b48Spatrick }
27409467b48Spatrick Terminator.Branch = &MI;
27509467b48Spatrick Terminator.TargetBlock =
27609467b48Spatrick TII->getBranchInfo(MI).getMBBTarget()->getNumber();
27709467b48Spatrick }
27809467b48Spatrick return Terminator;
27909467b48Spatrick }
28009467b48Spatrick
28109467b48Spatrick // Fill MBBs and Terminators, setting the addresses on the assumption
28209467b48Spatrick // that no branches need relaxation. Return the size of the function under
28309467b48Spatrick // this assumption.
initMBBInfo()28409467b48Spatrick uint64_t SystemZLongBranch::initMBBInfo() {
28509467b48Spatrick MF->RenumberBlocks();
28609467b48Spatrick unsigned NumBlocks = MF->size();
28709467b48Spatrick
28809467b48Spatrick MBBs.clear();
28909467b48Spatrick MBBs.resize(NumBlocks);
29009467b48Spatrick
29109467b48Spatrick Terminators.clear();
29209467b48Spatrick Terminators.reserve(NumBlocks);
29309467b48Spatrick
29409467b48Spatrick BlockPosition Position(Log2(MF->getAlignment()));
29509467b48Spatrick for (unsigned I = 0; I < NumBlocks; ++I) {
29609467b48Spatrick MachineBasicBlock *MBB = MF->getBlockNumbered(I);
29709467b48Spatrick MBBInfo &Block = MBBs[I];
29809467b48Spatrick
29909467b48Spatrick // Record the alignment, for quick access.
30009467b48Spatrick Block.Alignment = MBB->getAlignment();
30109467b48Spatrick
30209467b48Spatrick // Calculate the size of the fixed part of the block.
30309467b48Spatrick MachineBasicBlock::iterator MI = MBB->begin();
30409467b48Spatrick MachineBasicBlock::iterator End = MBB->end();
30509467b48Spatrick while (MI != End && !MI->isTerminator()) {
306*d415bd75Srobert Block.Size += getInstSizeInBytes(*MI, TII);
30709467b48Spatrick ++MI;
30809467b48Spatrick }
30909467b48Spatrick skipNonTerminators(Position, Block);
31009467b48Spatrick
31109467b48Spatrick // Add the terminators.
31209467b48Spatrick while (MI != End) {
31309467b48Spatrick if (!MI->isDebugInstr()) {
31409467b48Spatrick assert(MI->isTerminator() && "Terminator followed by non-terminator");
31509467b48Spatrick Terminators.push_back(describeTerminator(*MI));
31609467b48Spatrick skipTerminator(Position, Terminators.back(), false);
31709467b48Spatrick ++Block.NumTerminators;
31809467b48Spatrick }
31909467b48Spatrick ++MI;
32009467b48Spatrick }
32109467b48Spatrick }
32209467b48Spatrick
32309467b48Spatrick return Position.Address;
32409467b48Spatrick }
32509467b48Spatrick
32609467b48Spatrick // Return true if, under current assumptions, Terminator would need to be
32709467b48Spatrick // relaxed if it were placed at address Address.
mustRelaxBranch(const TerminatorInfo & Terminator,uint64_t Address)32809467b48Spatrick bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator,
32909467b48Spatrick uint64_t Address) {
33009467b48Spatrick if (!Terminator.Branch || Terminator.ExtraRelaxSize == 0)
33109467b48Spatrick return false;
33209467b48Spatrick
33309467b48Spatrick const MBBInfo &Target = MBBs[Terminator.TargetBlock];
33409467b48Spatrick if (Address >= Target.Address) {
33509467b48Spatrick if (Address - Target.Address <= MaxBackwardRange)
33609467b48Spatrick return false;
33709467b48Spatrick } else {
33809467b48Spatrick if (Target.Address - Address <= MaxForwardRange)
33909467b48Spatrick return false;
34009467b48Spatrick }
34109467b48Spatrick
34209467b48Spatrick return true;
34309467b48Spatrick }
34409467b48Spatrick
34509467b48Spatrick // Return true if, under current assumptions, any terminator needs
34609467b48Spatrick // to be relaxed.
mustRelaxABranch()34709467b48Spatrick bool SystemZLongBranch::mustRelaxABranch() {
34809467b48Spatrick for (auto &Terminator : Terminators)
34909467b48Spatrick if (mustRelaxBranch(Terminator, Terminator.Address))
35009467b48Spatrick return true;
35109467b48Spatrick return false;
35209467b48Spatrick }
35309467b48Spatrick
35409467b48Spatrick // Set the address of each block on the assumption that all branches
35509467b48Spatrick // must be long.
setWorstCaseAddresses()35609467b48Spatrick void SystemZLongBranch::setWorstCaseAddresses() {
35709467b48Spatrick SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
35809467b48Spatrick BlockPosition Position(Log2(MF->getAlignment()));
35909467b48Spatrick for (auto &Block : MBBs) {
36009467b48Spatrick skipNonTerminators(Position, Block);
36109467b48Spatrick for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) {
36209467b48Spatrick skipTerminator(Position, *TI, true);
36309467b48Spatrick ++TI;
36409467b48Spatrick }
36509467b48Spatrick }
36609467b48Spatrick }
36709467b48Spatrick
36809467b48Spatrick // Split BRANCH ON COUNT MI into the addition given by AddOpcode followed
36909467b48Spatrick // by a BRCL on the result.
splitBranchOnCount(MachineInstr * MI,unsigned AddOpcode)37009467b48Spatrick void SystemZLongBranch::splitBranchOnCount(MachineInstr *MI,
37109467b48Spatrick unsigned AddOpcode) {
37209467b48Spatrick MachineBasicBlock *MBB = MI->getParent();
37309467b48Spatrick DebugLoc DL = MI->getDebugLoc();
37409467b48Spatrick BuildMI(*MBB, MI, DL, TII->get(AddOpcode))
37509467b48Spatrick .add(MI->getOperand(0))
37609467b48Spatrick .add(MI->getOperand(1))
37709467b48Spatrick .addImm(-1);
37809467b48Spatrick MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL))
37909467b48Spatrick .addImm(SystemZ::CCMASK_ICMP)
38009467b48Spatrick .addImm(SystemZ::CCMASK_CMP_NE)
38109467b48Spatrick .add(MI->getOperand(2));
38209467b48Spatrick // The implicit use of CC is a killing use.
38309467b48Spatrick BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo());
38409467b48Spatrick MI->eraseFromParent();
38509467b48Spatrick }
38609467b48Spatrick
38709467b48Spatrick // Split MI into the comparison given by CompareOpcode followed
38809467b48Spatrick // a BRCL on the result.
splitCompareBranch(MachineInstr * MI,unsigned CompareOpcode)38909467b48Spatrick void SystemZLongBranch::splitCompareBranch(MachineInstr *MI,
39009467b48Spatrick unsigned CompareOpcode) {
39109467b48Spatrick MachineBasicBlock *MBB = MI->getParent();
39209467b48Spatrick DebugLoc DL = MI->getDebugLoc();
39309467b48Spatrick BuildMI(*MBB, MI, DL, TII->get(CompareOpcode))
39409467b48Spatrick .add(MI->getOperand(0))
39509467b48Spatrick .add(MI->getOperand(1));
39609467b48Spatrick MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL))
39709467b48Spatrick .addImm(SystemZ::CCMASK_ICMP)
39809467b48Spatrick .add(MI->getOperand(2))
39909467b48Spatrick .add(MI->getOperand(3));
40009467b48Spatrick // The implicit use of CC is a killing use.
40109467b48Spatrick BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo());
40209467b48Spatrick MI->eraseFromParent();
40309467b48Spatrick }
40409467b48Spatrick
40509467b48Spatrick // Relax the branch described by Terminator.
relaxBranch(TerminatorInfo & Terminator)40609467b48Spatrick void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
40709467b48Spatrick MachineInstr *Branch = Terminator.Branch;
40809467b48Spatrick switch (Branch->getOpcode()) {
40909467b48Spatrick case SystemZ::J:
41009467b48Spatrick Branch->setDesc(TII->get(SystemZ::JG));
41109467b48Spatrick break;
41209467b48Spatrick case SystemZ::BRC:
41309467b48Spatrick Branch->setDesc(TII->get(SystemZ::BRCL));
41409467b48Spatrick break;
41509467b48Spatrick case SystemZ::BRCT:
41609467b48Spatrick splitBranchOnCount(Branch, SystemZ::AHI);
41709467b48Spatrick break;
41809467b48Spatrick case SystemZ::BRCTG:
41909467b48Spatrick splitBranchOnCount(Branch, SystemZ::AGHI);
42009467b48Spatrick break;
42109467b48Spatrick case SystemZ::CRJ:
42209467b48Spatrick splitCompareBranch(Branch, SystemZ::CR);
42309467b48Spatrick break;
42409467b48Spatrick case SystemZ::CGRJ:
42509467b48Spatrick splitCompareBranch(Branch, SystemZ::CGR);
42609467b48Spatrick break;
42709467b48Spatrick case SystemZ::CIJ:
42809467b48Spatrick splitCompareBranch(Branch, SystemZ::CHI);
42909467b48Spatrick break;
43009467b48Spatrick case SystemZ::CGIJ:
43109467b48Spatrick splitCompareBranch(Branch, SystemZ::CGHI);
43209467b48Spatrick break;
43309467b48Spatrick case SystemZ::CLRJ:
43409467b48Spatrick splitCompareBranch(Branch, SystemZ::CLR);
43509467b48Spatrick break;
43609467b48Spatrick case SystemZ::CLGRJ:
43709467b48Spatrick splitCompareBranch(Branch, SystemZ::CLGR);
43809467b48Spatrick break;
43909467b48Spatrick case SystemZ::CLIJ:
44009467b48Spatrick splitCompareBranch(Branch, SystemZ::CLFI);
44109467b48Spatrick break;
44209467b48Spatrick case SystemZ::CLGIJ:
44309467b48Spatrick splitCompareBranch(Branch, SystemZ::CLGFI);
44409467b48Spatrick break;
44509467b48Spatrick default:
44609467b48Spatrick llvm_unreachable("Unrecognized branch");
44709467b48Spatrick }
44809467b48Spatrick
44909467b48Spatrick Terminator.Size += Terminator.ExtraRelaxSize;
45009467b48Spatrick Terminator.ExtraRelaxSize = 0;
45109467b48Spatrick Terminator.Branch = nullptr;
45209467b48Spatrick
45309467b48Spatrick ++LongBranches;
45409467b48Spatrick }
45509467b48Spatrick
45609467b48Spatrick // Run a shortening pass and relax any branches that need to be relaxed.
relaxBranches()45709467b48Spatrick void SystemZLongBranch::relaxBranches() {
45809467b48Spatrick SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
45909467b48Spatrick BlockPosition Position(Log2(MF->getAlignment()));
46009467b48Spatrick for (auto &Block : MBBs) {
46109467b48Spatrick skipNonTerminators(Position, Block);
46209467b48Spatrick for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) {
46309467b48Spatrick assert(Position.Address <= TI->Address &&
46409467b48Spatrick "Addresses shouldn't go forwards");
46509467b48Spatrick if (mustRelaxBranch(*TI, Position.Address))
46609467b48Spatrick relaxBranch(*TI);
46709467b48Spatrick skipTerminator(Position, *TI, false);
46809467b48Spatrick ++TI;
46909467b48Spatrick }
47009467b48Spatrick }
47109467b48Spatrick }
47209467b48Spatrick
runOnMachineFunction(MachineFunction & F)47309467b48Spatrick bool SystemZLongBranch::runOnMachineFunction(MachineFunction &F) {
47409467b48Spatrick TII = static_cast<const SystemZInstrInfo *>(F.getSubtarget().getInstrInfo());
47509467b48Spatrick MF = &F;
47609467b48Spatrick uint64_t Size = initMBBInfo();
47709467b48Spatrick if (Size <= MaxForwardRange || !mustRelaxABranch())
47809467b48Spatrick return false;
47909467b48Spatrick
48009467b48Spatrick setWorstCaseAddresses();
48109467b48Spatrick relaxBranches();
48209467b48Spatrick return true;
48309467b48Spatrick }
48409467b48Spatrick
createSystemZLongBranchPass(SystemZTargetMachine & TM)48509467b48Spatrick FunctionPass *llvm::createSystemZLongBranchPass(SystemZTargetMachine &TM) {
486*d415bd75Srobert return new SystemZLongBranch();
48709467b48Spatrick }
488