xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric //===-- SystemZLongBranch.cpp - Branch lengthening for SystemZ ------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This pass makes sure that all branches are in range.  There are several ways
100b57cec5SDimitry Andric // in which this could be done.  One aggressive approach is to assume that all
110b57cec5SDimitry Andric // branches are in range and successively replace those that turn out not
120b57cec5SDimitry Andric // to be in range with a longer form (branch relaxation).  A simple
130b57cec5SDimitry Andric // implementation is to continually walk through the function relaxing
140b57cec5SDimitry Andric // branches until no more changes are needed and a fixed point is reached.
150b57cec5SDimitry Andric // However, in the pathological worst case, this implementation is
160b57cec5SDimitry Andric // quadratic in the number of blocks; relaxing branch N can make branch N-1
170b57cec5SDimitry Andric // go out of range, which in turn can make branch N-2 go out of range,
180b57cec5SDimitry Andric // and so on.
190b57cec5SDimitry Andric //
200b57cec5SDimitry Andric // An alternative approach is to assume that all branches must be
210b57cec5SDimitry Andric // converted to their long forms, then reinstate the short forms of
220b57cec5SDimitry Andric // branches that, even under this pessimistic assumption, turn out to be
230b57cec5SDimitry Andric // in range (branch shortening).  This too can be implemented as a function
240b57cec5SDimitry Andric // walk that is repeated until a fixed point is reached.  In general,
250b57cec5SDimitry Andric // the result of shortening is not as good as that of relaxation, and
260b57cec5SDimitry Andric // shortening is also quadratic in the worst case; shortening branch N
270b57cec5SDimitry Andric // can bring branch N-1 in range of the short form, which in turn can do
280b57cec5SDimitry Andric // the same for branch N-2, and so on.  The main advantage of shortening
290b57cec5SDimitry Andric // is that each walk through the function produces valid code, so it is
300b57cec5SDimitry Andric // possible to stop at any point after the first walk.  The quadraticness
310b57cec5SDimitry Andric // could therefore be handled with a maximum pass count, although the
320b57cec5SDimitry Andric // question then becomes: what maximum count should be used?
330b57cec5SDimitry Andric //
340b57cec5SDimitry Andric // On SystemZ, long branches are only needed for functions bigger than 64k,
350b57cec5SDimitry Andric // which are relatively rare to begin with, and the long branch sequences
360b57cec5SDimitry Andric // are actually relatively cheap.  It therefore doesn't seem worth spending
370b57cec5SDimitry Andric // much compilation time on the problem.  Instead, the approach we take is:
380b57cec5SDimitry Andric //
390b57cec5SDimitry Andric // (1) Work out the address that each block would have if no branches
400b57cec5SDimitry Andric //     need relaxing.  Exit the pass early if all branches are in range
410b57cec5SDimitry Andric //     according to this assumption.
420b57cec5SDimitry Andric //
430b57cec5SDimitry Andric // (2) Work out the address that each block would have if all branches
440b57cec5SDimitry Andric //     need relaxing.
450b57cec5SDimitry Andric //
460b57cec5SDimitry Andric // (3) Walk through the block calculating the final address of each instruction
470b57cec5SDimitry Andric //     and relaxing those that need to be relaxed.  For backward branches,
480b57cec5SDimitry Andric //     this check uses the final address of the target block, as calculated
490b57cec5SDimitry Andric //     earlier in the walk.  For forward branches, this check uses the
500b57cec5SDimitry Andric //     address of the target block that was calculated in (2).  Both checks
510b57cec5SDimitry Andric //     give a conservatively-correct range.
520b57cec5SDimitry Andric //
530b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric #include "SystemZ.h"
560b57cec5SDimitry Andric #include "SystemZInstrInfo.h"
570b57cec5SDimitry Andric #include "SystemZTargetMachine.h"
580b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
590b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
600b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
610b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
620b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
630b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
640b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
650b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
660b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h"
670b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
680b57cec5SDimitry Andric #include <cassert>
690b57cec5SDimitry Andric #include <cstdint>
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric using namespace llvm;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric #define DEBUG_TYPE "systemz-long-branch"
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric STATISTIC(LongBranches, "Number of long branches.");
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric namespace {
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric // Represents positional information about a basic block.
800b57cec5SDimitry Andric struct MBBInfo {
810b57cec5SDimitry Andric   // The address that we currently assume the block has.
820b57cec5SDimitry Andric   uint64_t Address = 0;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   // The size of the block in bytes, excluding terminators.
850b57cec5SDimitry Andric   // This value never changes.
860b57cec5SDimitry Andric   uint64_t Size = 0;
870b57cec5SDimitry Andric 
888bcb0991SDimitry Andric   // The minimum alignment of the block.
890b57cec5SDimitry Andric   // This value never changes.
908bcb0991SDimitry Andric   Align Alignment;
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   // The number of terminators in this block.  This value never changes.
930b57cec5SDimitry Andric   unsigned NumTerminators = 0;
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   MBBInfo() = default;
960b57cec5SDimitry Andric };
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric // Represents the state of a block terminator.
990b57cec5SDimitry Andric struct TerminatorInfo {
1000b57cec5SDimitry Andric   // If this terminator is a relaxable branch, this points to the branch
1010b57cec5SDimitry Andric   // instruction, otherwise it is null.
1020b57cec5SDimitry Andric   MachineInstr *Branch = nullptr;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   // The address that we currently assume the terminator has.
1050b57cec5SDimitry Andric   uint64_t Address = 0;
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   // The current size of the terminator in bytes.
1080b57cec5SDimitry Andric   uint64_t Size = 0;
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   // If Branch is nonnull, this is the number of the target block,
1110b57cec5SDimitry Andric   // otherwise it is unused.
1120b57cec5SDimitry Andric   unsigned TargetBlock = 0;
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   // If Branch is nonnull, this is the length of the longest relaxed form,
1150b57cec5SDimitry Andric   // otherwise it is zero.
1160b57cec5SDimitry Andric   unsigned ExtraRelaxSize = 0;
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   TerminatorInfo() = default;
1190b57cec5SDimitry Andric };
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric // Used to keep track of the current position while iterating over the blocks.
1220b57cec5SDimitry Andric struct BlockPosition {
1230b57cec5SDimitry Andric   // The address that we assume this position has.
1240b57cec5SDimitry Andric   uint64_t Address = 0;
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   // The number of low bits in Address that are known to be the same
1270b57cec5SDimitry Andric   // as the runtime address.
1280b57cec5SDimitry Andric   unsigned KnownBits;
1290b57cec5SDimitry Andric 
BlockPosition__anon67c54ec30111::BlockPosition1308bcb0991SDimitry Andric   BlockPosition(unsigned InitialLogAlignment)
1318bcb0991SDimitry Andric       : KnownBits(InitialLogAlignment) {}
1320b57cec5SDimitry Andric };
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric class SystemZLongBranch : public MachineFunctionPass {
1350b57cec5SDimitry Andric public:
1360b57cec5SDimitry Andric   static char ID;
1370b57cec5SDimitry Andric 
SystemZLongBranch()13804eeddc0SDimitry Andric   SystemZLongBranch() : MachineFunctionPass(ID) {
13904eeddc0SDimitry Andric     initializeSystemZLongBranchPass(*PassRegistry::getPassRegistry());
14004eeddc0SDimitry Andric   }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &F) override;
1430b57cec5SDimitry Andric 
getRequiredProperties() const1440b57cec5SDimitry Andric   MachineFunctionProperties getRequiredProperties() const override {
1450b57cec5SDimitry Andric     return MachineFunctionProperties().set(
1460b57cec5SDimitry Andric         MachineFunctionProperties::Property::NoVRegs);
1470b57cec5SDimitry Andric   }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric private:
1500b57cec5SDimitry Andric   void skipNonTerminators(BlockPosition &Position, MBBInfo &Block);
1510b57cec5SDimitry Andric   void skipTerminator(BlockPosition &Position, TerminatorInfo &Terminator,
1520b57cec5SDimitry Andric                       bool AssumeRelaxed);
1530b57cec5SDimitry Andric   TerminatorInfo describeTerminator(MachineInstr &MI);
1540b57cec5SDimitry Andric   uint64_t initMBBInfo();
1550b57cec5SDimitry Andric   bool mustRelaxBranch(const TerminatorInfo &Terminator, uint64_t Address);
1560b57cec5SDimitry Andric   bool mustRelaxABranch();
1570b57cec5SDimitry Andric   void setWorstCaseAddresses();
1580b57cec5SDimitry Andric   void splitBranchOnCount(MachineInstr *MI, unsigned AddOpcode);
1590b57cec5SDimitry Andric   void splitCompareBranch(MachineInstr *MI, unsigned CompareOpcode);
1600b57cec5SDimitry Andric   void relaxBranch(TerminatorInfo &Terminator);
1610b57cec5SDimitry Andric   void relaxBranches();
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   const SystemZInstrInfo *TII = nullptr;
164480093f4SDimitry Andric   MachineFunction *MF = nullptr;
1650b57cec5SDimitry Andric   SmallVector<MBBInfo, 16> MBBs;
1660b57cec5SDimitry Andric   SmallVector<TerminatorInfo, 16> Terminators;
1670b57cec5SDimitry Andric };
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric char SystemZLongBranch::ID = 0;
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric const uint64_t MaxBackwardRange = 0x10000;
1720b57cec5SDimitry Andric const uint64_t MaxForwardRange = 0xfffe;
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric } // end anonymous namespace
1750b57cec5SDimitry Andric 
17604eeddc0SDimitry Andric INITIALIZE_PASS(SystemZLongBranch, DEBUG_TYPE, "SystemZ Long Branch", false,
17704eeddc0SDimitry Andric                 false)
17804eeddc0SDimitry Andric 
1790b57cec5SDimitry Andric // Position describes the state immediately before Block.  Update Block
1800b57cec5SDimitry Andric // accordingly and move Position to the end of the block's non-terminator
1810b57cec5SDimitry Andric // instructions.
skipNonTerminators(BlockPosition & Position,MBBInfo & Block)1820b57cec5SDimitry Andric void SystemZLongBranch::skipNonTerminators(BlockPosition &Position,
1830b57cec5SDimitry Andric                                            MBBInfo &Block) {
1848bcb0991SDimitry Andric   if (Log2(Block.Alignment) > Position.KnownBits) {
1850b57cec5SDimitry Andric     // When calculating the address of Block, we need to conservatively
1860b57cec5SDimitry Andric     // assume that Block had the worst possible misalignment.
1878bcb0991SDimitry Andric     Position.Address +=
1888bcb0991SDimitry Andric         (Block.Alignment.value() - (uint64_t(1) << Position.KnownBits));
1898bcb0991SDimitry Andric     Position.KnownBits = Log2(Block.Alignment);
1900b57cec5SDimitry Andric   }
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   // Align the addresses.
1938bcb0991SDimitry Andric   Position.Address = alignTo(Position.Address, Block.Alignment);
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   // Record the block's position.
1960b57cec5SDimitry Andric   Block.Address = Position.Address;
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   // Move past the non-terminators in the block.
1990b57cec5SDimitry Andric   Position.Address += Block.Size;
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric // Position describes the state immediately before Terminator.
2030b57cec5SDimitry Andric // Update Terminator accordingly and move Position past it.
2040b57cec5SDimitry Andric // Assume that Terminator will be relaxed if AssumeRelaxed.
skipTerminator(BlockPosition & Position,TerminatorInfo & Terminator,bool AssumeRelaxed)2050b57cec5SDimitry Andric void SystemZLongBranch::skipTerminator(BlockPosition &Position,
2060b57cec5SDimitry Andric                                        TerminatorInfo &Terminator,
2070b57cec5SDimitry Andric                                        bool AssumeRelaxed) {
2080b57cec5SDimitry Andric   Terminator.Address = Position.Address;
2090b57cec5SDimitry Andric   Position.Address += Terminator.Size;
2100b57cec5SDimitry Andric   if (AssumeRelaxed)
2110b57cec5SDimitry Andric     Position.Address += Terminator.ExtraRelaxSize;
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric 
getInstSizeInBytes(const MachineInstr & MI,const SystemZInstrInfo * TII)214349cc55cSDimitry Andric static unsigned getInstSizeInBytes(const MachineInstr &MI,
215349cc55cSDimitry Andric                                    const SystemZInstrInfo *TII) {
216349cc55cSDimitry Andric   unsigned Size = TII->getInstSizeInBytes(MI);
217349cc55cSDimitry Andric   assert((Size ||
218349cc55cSDimitry Andric           // These do not have a size:
219349cc55cSDimitry Andric           MI.isDebugOrPseudoInstr() || MI.isPosition() || MI.isKill() ||
220*bdd1243dSDimitry Andric           MI.isImplicitDef() || MI.getOpcode() == TargetOpcode::MEMBARRIER ||
221349cc55cSDimitry Andric           // These have a size that may be zero:
222349cc55cSDimitry Andric           MI.isInlineAsm() || MI.getOpcode() == SystemZ::STACKMAP ||
223349cc55cSDimitry Andric           MI.getOpcode() == SystemZ::PATCHPOINT) &&
224349cc55cSDimitry Andric          "Missing size value for instruction.");
225349cc55cSDimitry Andric   return Size;
226349cc55cSDimitry Andric }
227349cc55cSDimitry Andric 
2280b57cec5SDimitry Andric // Return a description of terminator instruction MI.
describeTerminator(MachineInstr & MI)2290b57cec5SDimitry Andric TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr &MI) {
2300b57cec5SDimitry Andric   TerminatorInfo Terminator;
231349cc55cSDimitry Andric   Terminator.Size = getInstSizeInBytes(MI, TII);
2320b57cec5SDimitry Andric   if (MI.isConditionalBranch() || MI.isUnconditionalBranch()) {
2330b57cec5SDimitry Andric     switch (MI.getOpcode()) {
2340b57cec5SDimitry Andric     case SystemZ::J:
2350b57cec5SDimitry Andric       // Relaxes to JG, which is 2 bytes longer.
2360b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 2;
2370b57cec5SDimitry Andric       break;
2380b57cec5SDimitry Andric     case SystemZ::BRC:
2390b57cec5SDimitry Andric       // Relaxes to BRCL, which is 2 bytes longer.
2400b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 2;
2410b57cec5SDimitry Andric       break;
2420b57cec5SDimitry Andric     case SystemZ::BRCT:
2430b57cec5SDimitry Andric     case SystemZ::BRCTG:
2440b57cec5SDimitry Andric       // Relaxes to A(G)HI and BRCL, which is 6 bytes longer.
2450b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 6;
2460b57cec5SDimitry Andric       break;
2470b57cec5SDimitry Andric     case SystemZ::BRCTH:
2480b57cec5SDimitry Andric       // Never needs to be relaxed.
2490b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 0;
2500b57cec5SDimitry Andric       break;
2510b57cec5SDimitry Andric     case SystemZ::CRJ:
2520b57cec5SDimitry Andric     case SystemZ::CLRJ:
2530b57cec5SDimitry Andric       // Relaxes to a C(L)R/BRCL sequence, which is 2 bytes longer.
2540b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 2;
2550b57cec5SDimitry Andric       break;
2560b57cec5SDimitry Andric     case SystemZ::CGRJ:
2570b57cec5SDimitry Andric     case SystemZ::CLGRJ:
2580b57cec5SDimitry Andric       // Relaxes to a C(L)GR/BRCL sequence, which is 4 bytes longer.
2590b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 4;
2600b57cec5SDimitry Andric       break;
2610b57cec5SDimitry Andric     case SystemZ::CIJ:
2620b57cec5SDimitry Andric     case SystemZ::CGIJ:
2630b57cec5SDimitry Andric       // Relaxes to a C(G)HI/BRCL sequence, which is 4 bytes longer.
2640b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 4;
2650b57cec5SDimitry Andric       break;
2660b57cec5SDimitry Andric     case SystemZ::CLIJ:
2670b57cec5SDimitry Andric     case SystemZ::CLGIJ:
2680b57cec5SDimitry Andric       // Relaxes to a CL(G)FI/BRCL sequence, which is 6 bytes longer.
2690b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 6;
2700b57cec5SDimitry Andric       break;
2710b57cec5SDimitry Andric     default:
2720b57cec5SDimitry Andric       llvm_unreachable("Unrecognized branch instruction");
2730b57cec5SDimitry Andric     }
2740b57cec5SDimitry Andric     Terminator.Branch = &MI;
2750b57cec5SDimitry Andric     Terminator.TargetBlock =
2760b57cec5SDimitry Andric       TII->getBranchInfo(MI).getMBBTarget()->getNumber();
2770b57cec5SDimitry Andric   }
2780b57cec5SDimitry Andric   return Terminator;
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric // Fill MBBs and Terminators, setting the addresses on the assumption
2820b57cec5SDimitry Andric // that no branches need relaxation.  Return the size of the function under
2830b57cec5SDimitry Andric // this assumption.
initMBBInfo()2840b57cec5SDimitry Andric uint64_t SystemZLongBranch::initMBBInfo() {
2850b57cec5SDimitry Andric   MF->RenumberBlocks();
2860b57cec5SDimitry Andric   unsigned NumBlocks = MF->size();
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   MBBs.clear();
2890b57cec5SDimitry Andric   MBBs.resize(NumBlocks);
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   Terminators.clear();
2920b57cec5SDimitry Andric   Terminators.reserve(NumBlocks);
2930b57cec5SDimitry Andric 
2948bcb0991SDimitry Andric   BlockPosition Position(Log2(MF->getAlignment()));
2950b57cec5SDimitry Andric   for (unsigned I = 0; I < NumBlocks; ++I) {
2960b57cec5SDimitry Andric     MachineBasicBlock *MBB = MF->getBlockNumbered(I);
2970b57cec5SDimitry Andric     MBBInfo &Block = MBBs[I];
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric     // Record the alignment, for quick access.
3000b57cec5SDimitry Andric     Block.Alignment = MBB->getAlignment();
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric     // Calculate the size of the fixed part of the block.
3030b57cec5SDimitry Andric     MachineBasicBlock::iterator MI = MBB->begin();
3040b57cec5SDimitry Andric     MachineBasicBlock::iterator End = MBB->end();
3050b57cec5SDimitry Andric     while (MI != End && !MI->isTerminator()) {
306349cc55cSDimitry Andric       Block.Size += getInstSizeInBytes(*MI, TII);
3070b57cec5SDimitry Andric       ++MI;
3080b57cec5SDimitry Andric     }
3090b57cec5SDimitry Andric     skipNonTerminators(Position, Block);
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric     // Add the terminators.
3120b57cec5SDimitry Andric     while (MI != End) {
3130b57cec5SDimitry Andric       if (!MI->isDebugInstr()) {
3140b57cec5SDimitry Andric         assert(MI->isTerminator() && "Terminator followed by non-terminator");
3150b57cec5SDimitry Andric         Terminators.push_back(describeTerminator(*MI));
3160b57cec5SDimitry Andric         skipTerminator(Position, Terminators.back(), false);
3170b57cec5SDimitry Andric         ++Block.NumTerminators;
3180b57cec5SDimitry Andric       }
3190b57cec5SDimitry Andric       ++MI;
3200b57cec5SDimitry Andric     }
3210b57cec5SDimitry Andric   }
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric   return Position.Address;
3240b57cec5SDimitry Andric }
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric // Return true if, under current assumptions, Terminator would need to be
3270b57cec5SDimitry Andric // relaxed if it were placed at address Address.
mustRelaxBranch(const TerminatorInfo & Terminator,uint64_t Address)3280b57cec5SDimitry Andric bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator,
3290b57cec5SDimitry Andric                                         uint64_t Address) {
3300b57cec5SDimitry Andric   if (!Terminator.Branch || Terminator.ExtraRelaxSize == 0)
3310b57cec5SDimitry Andric     return false;
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   const MBBInfo &Target = MBBs[Terminator.TargetBlock];
3340b57cec5SDimitry Andric   if (Address >= Target.Address) {
3350b57cec5SDimitry Andric     if (Address - Target.Address <= MaxBackwardRange)
3360b57cec5SDimitry Andric       return false;
3370b57cec5SDimitry Andric   } else {
3380b57cec5SDimitry Andric     if (Target.Address - Address <= MaxForwardRange)
3390b57cec5SDimitry Andric       return false;
3400b57cec5SDimitry Andric   }
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric   return true;
3430b57cec5SDimitry Andric }
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric // Return true if, under current assumptions, any terminator needs
3460b57cec5SDimitry Andric // to be relaxed.
mustRelaxABranch()3470b57cec5SDimitry Andric bool SystemZLongBranch::mustRelaxABranch() {
3480b57cec5SDimitry Andric   for (auto &Terminator : Terminators)
3490b57cec5SDimitry Andric     if (mustRelaxBranch(Terminator, Terminator.Address))
3500b57cec5SDimitry Andric       return true;
3510b57cec5SDimitry Andric   return false;
3520b57cec5SDimitry Andric }
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric // Set the address of each block on the assumption that all branches
3550b57cec5SDimitry Andric // must be long.
setWorstCaseAddresses()3560b57cec5SDimitry Andric void SystemZLongBranch::setWorstCaseAddresses() {
3570b57cec5SDimitry Andric   SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
3588bcb0991SDimitry Andric   BlockPosition Position(Log2(MF->getAlignment()));
3590b57cec5SDimitry Andric   for (auto &Block : MBBs) {
3600b57cec5SDimitry Andric     skipNonTerminators(Position, Block);
3610b57cec5SDimitry Andric     for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) {
3620b57cec5SDimitry Andric       skipTerminator(Position, *TI, true);
3630b57cec5SDimitry Andric       ++TI;
3640b57cec5SDimitry Andric     }
3650b57cec5SDimitry Andric   }
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric // Split BRANCH ON COUNT MI into the addition given by AddOpcode followed
3690b57cec5SDimitry Andric // by a BRCL on the result.
splitBranchOnCount(MachineInstr * MI,unsigned AddOpcode)3700b57cec5SDimitry Andric void SystemZLongBranch::splitBranchOnCount(MachineInstr *MI,
3710b57cec5SDimitry Andric                                            unsigned AddOpcode) {
3720b57cec5SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
3730b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
3740b57cec5SDimitry Andric   BuildMI(*MBB, MI, DL, TII->get(AddOpcode))
3750b57cec5SDimitry Andric       .add(MI->getOperand(0))
3760b57cec5SDimitry Andric       .add(MI->getOperand(1))
3770b57cec5SDimitry Andric       .addImm(-1);
3780b57cec5SDimitry Andric   MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL))
3790b57cec5SDimitry Andric                            .addImm(SystemZ::CCMASK_ICMP)
3800b57cec5SDimitry Andric                            .addImm(SystemZ::CCMASK_CMP_NE)
3810b57cec5SDimitry Andric                            .add(MI->getOperand(2));
3820b57cec5SDimitry Andric   // The implicit use of CC is a killing use.
3830b57cec5SDimitry Andric   BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo());
3840b57cec5SDimitry Andric   MI->eraseFromParent();
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric // Split MI into the comparison given by CompareOpcode followed
3880b57cec5SDimitry Andric // a BRCL on the result.
splitCompareBranch(MachineInstr * MI,unsigned CompareOpcode)3890b57cec5SDimitry Andric void SystemZLongBranch::splitCompareBranch(MachineInstr *MI,
3900b57cec5SDimitry Andric                                            unsigned CompareOpcode) {
3910b57cec5SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
3920b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
3930b57cec5SDimitry Andric   BuildMI(*MBB, MI, DL, TII->get(CompareOpcode))
3940b57cec5SDimitry Andric       .add(MI->getOperand(0))
3950b57cec5SDimitry Andric       .add(MI->getOperand(1));
3960b57cec5SDimitry Andric   MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL))
3970b57cec5SDimitry Andric                            .addImm(SystemZ::CCMASK_ICMP)
3980b57cec5SDimitry Andric                            .add(MI->getOperand(2))
3990b57cec5SDimitry Andric                            .add(MI->getOperand(3));
4000b57cec5SDimitry Andric   // The implicit use of CC is a killing use.
4010b57cec5SDimitry Andric   BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo());
4020b57cec5SDimitry Andric   MI->eraseFromParent();
4030b57cec5SDimitry Andric }
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric // Relax the branch described by Terminator.
relaxBranch(TerminatorInfo & Terminator)4060b57cec5SDimitry Andric void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
4070b57cec5SDimitry Andric   MachineInstr *Branch = Terminator.Branch;
4080b57cec5SDimitry Andric   switch (Branch->getOpcode()) {
4090b57cec5SDimitry Andric   case SystemZ::J:
4100b57cec5SDimitry Andric     Branch->setDesc(TII->get(SystemZ::JG));
4110b57cec5SDimitry Andric     break;
4120b57cec5SDimitry Andric   case SystemZ::BRC:
4130b57cec5SDimitry Andric     Branch->setDesc(TII->get(SystemZ::BRCL));
4140b57cec5SDimitry Andric     break;
4150b57cec5SDimitry Andric   case SystemZ::BRCT:
4160b57cec5SDimitry Andric     splitBranchOnCount(Branch, SystemZ::AHI);
4170b57cec5SDimitry Andric     break;
4180b57cec5SDimitry Andric   case SystemZ::BRCTG:
4190b57cec5SDimitry Andric     splitBranchOnCount(Branch, SystemZ::AGHI);
4200b57cec5SDimitry Andric     break;
4210b57cec5SDimitry Andric   case SystemZ::CRJ:
4220b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CR);
4230b57cec5SDimitry Andric     break;
4240b57cec5SDimitry Andric   case SystemZ::CGRJ:
4250b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CGR);
4260b57cec5SDimitry Andric     break;
4270b57cec5SDimitry Andric   case SystemZ::CIJ:
4280b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CHI);
4290b57cec5SDimitry Andric     break;
4300b57cec5SDimitry Andric   case SystemZ::CGIJ:
4310b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CGHI);
4320b57cec5SDimitry Andric     break;
4330b57cec5SDimitry Andric   case SystemZ::CLRJ:
4340b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CLR);
4350b57cec5SDimitry Andric     break;
4360b57cec5SDimitry Andric   case SystemZ::CLGRJ:
4370b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CLGR);
4380b57cec5SDimitry Andric     break;
4390b57cec5SDimitry Andric   case SystemZ::CLIJ:
4400b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CLFI);
4410b57cec5SDimitry Andric     break;
4420b57cec5SDimitry Andric   case SystemZ::CLGIJ:
4430b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CLGFI);
4440b57cec5SDimitry Andric     break;
4450b57cec5SDimitry Andric   default:
4460b57cec5SDimitry Andric     llvm_unreachable("Unrecognized branch");
4470b57cec5SDimitry Andric   }
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric   Terminator.Size += Terminator.ExtraRelaxSize;
4500b57cec5SDimitry Andric   Terminator.ExtraRelaxSize = 0;
4510b57cec5SDimitry Andric   Terminator.Branch = nullptr;
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric   ++LongBranches;
4540b57cec5SDimitry Andric }
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric // Run a shortening pass and relax any branches that need to be relaxed.
relaxBranches()4570b57cec5SDimitry Andric void SystemZLongBranch::relaxBranches() {
4580b57cec5SDimitry Andric   SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
4598bcb0991SDimitry Andric   BlockPosition Position(Log2(MF->getAlignment()));
4600b57cec5SDimitry Andric   for (auto &Block : MBBs) {
4610b57cec5SDimitry Andric     skipNonTerminators(Position, Block);
4620b57cec5SDimitry Andric     for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) {
4630b57cec5SDimitry Andric       assert(Position.Address <= TI->Address &&
4640b57cec5SDimitry Andric              "Addresses shouldn't go forwards");
4650b57cec5SDimitry Andric       if (mustRelaxBranch(*TI, Position.Address))
4660b57cec5SDimitry Andric         relaxBranch(*TI);
4670b57cec5SDimitry Andric       skipTerminator(Position, *TI, false);
4680b57cec5SDimitry Andric       ++TI;
4690b57cec5SDimitry Andric     }
4700b57cec5SDimitry Andric   }
4710b57cec5SDimitry Andric }
4720b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & F)4730b57cec5SDimitry Andric bool SystemZLongBranch::runOnMachineFunction(MachineFunction &F) {
4740b57cec5SDimitry Andric   TII = static_cast<const SystemZInstrInfo *>(F.getSubtarget().getInstrInfo());
4750b57cec5SDimitry Andric   MF = &F;
4760b57cec5SDimitry Andric   uint64_t Size = initMBBInfo();
4770b57cec5SDimitry Andric   if (Size <= MaxForwardRange || !mustRelaxABranch())
4780b57cec5SDimitry Andric     return false;
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric   setWorstCaseAddresses();
4810b57cec5SDimitry Andric   relaxBranches();
4820b57cec5SDimitry Andric   return true;
4830b57cec5SDimitry Andric }
4840b57cec5SDimitry Andric 
createSystemZLongBranchPass(SystemZTargetMachine & TM)4850b57cec5SDimitry Andric FunctionPass *llvm::createSystemZLongBranchPass(SystemZTargetMachine &TM) {
48604eeddc0SDimitry Andric   return new SystemZLongBranch();
4870b57cec5SDimitry Andric }
488