xref: /openbsd-src/gnu/llvm/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
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