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