xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
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 
1308bcb0991SDimitry 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 
1380b57cec5SDimitry Andric   SystemZLongBranch(const SystemZTargetMachine &tm)
1390b57cec5SDimitry Andric     : MachineFunctionPass(ID) {}
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   StringRef getPassName() const override { return "SystemZ Long Branch"; }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &F) override;
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   MachineFunctionProperties getRequiredProperties() const override {
1460b57cec5SDimitry Andric     return MachineFunctionProperties().set(
1470b57cec5SDimitry Andric         MachineFunctionProperties::Property::NoVRegs);
1480b57cec5SDimitry Andric   }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric private:
1510b57cec5SDimitry Andric   void skipNonTerminators(BlockPosition &Position, MBBInfo &Block);
1520b57cec5SDimitry Andric   void skipTerminator(BlockPosition &Position, TerminatorInfo &Terminator,
1530b57cec5SDimitry Andric                       bool AssumeRelaxed);
1540b57cec5SDimitry Andric   TerminatorInfo describeTerminator(MachineInstr &MI);
1550b57cec5SDimitry Andric   uint64_t initMBBInfo();
1560b57cec5SDimitry Andric   bool mustRelaxBranch(const TerminatorInfo &Terminator, uint64_t Address);
1570b57cec5SDimitry Andric   bool mustRelaxABranch();
1580b57cec5SDimitry Andric   void setWorstCaseAddresses();
1590b57cec5SDimitry Andric   void splitBranchOnCount(MachineInstr *MI, unsigned AddOpcode);
1600b57cec5SDimitry Andric   void splitCompareBranch(MachineInstr *MI, unsigned CompareOpcode);
1610b57cec5SDimitry Andric   void relaxBranch(TerminatorInfo &Terminator);
1620b57cec5SDimitry Andric   void relaxBranches();
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   const SystemZInstrInfo *TII = nullptr;
165480093f4SDimitry Andric   MachineFunction *MF = nullptr;
1660b57cec5SDimitry Andric   SmallVector<MBBInfo, 16> MBBs;
1670b57cec5SDimitry Andric   SmallVector<TerminatorInfo, 16> Terminators;
1680b57cec5SDimitry Andric };
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric char SystemZLongBranch::ID = 0;
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric const uint64_t MaxBackwardRange = 0x10000;
1730b57cec5SDimitry Andric const uint64_t MaxForwardRange = 0xfffe;
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric } // end anonymous namespace
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric // Position describes the state immediately before Block.  Update Block
1780b57cec5SDimitry Andric // accordingly and move Position to the end of the block's non-terminator
1790b57cec5SDimitry Andric // instructions.
1800b57cec5SDimitry Andric void SystemZLongBranch::skipNonTerminators(BlockPosition &Position,
1810b57cec5SDimitry Andric                                            MBBInfo &Block) {
1828bcb0991SDimitry Andric   if (Log2(Block.Alignment) > Position.KnownBits) {
1830b57cec5SDimitry Andric     // When calculating the address of Block, we need to conservatively
1840b57cec5SDimitry Andric     // assume that Block had the worst possible misalignment.
1858bcb0991SDimitry Andric     Position.Address +=
1868bcb0991SDimitry Andric         (Block.Alignment.value() - (uint64_t(1) << Position.KnownBits));
1878bcb0991SDimitry Andric     Position.KnownBits = Log2(Block.Alignment);
1880b57cec5SDimitry Andric   }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   // Align the addresses.
1918bcb0991SDimitry Andric   Position.Address = alignTo(Position.Address, Block.Alignment);
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   // Record the block's position.
1940b57cec5SDimitry Andric   Block.Address = Position.Address;
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric   // Move past the non-terminators in the block.
1970b57cec5SDimitry Andric   Position.Address += Block.Size;
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric // Position describes the state immediately before Terminator.
2010b57cec5SDimitry Andric // Update Terminator accordingly and move Position past it.
2020b57cec5SDimitry Andric // Assume that Terminator will be relaxed if AssumeRelaxed.
2030b57cec5SDimitry Andric void SystemZLongBranch::skipTerminator(BlockPosition &Position,
2040b57cec5SDimitry Andric                                        TerminatorInfo &Terminator,
2050b57cec5SDimitry Andric                                        bool AssumeRelaxed) {
2060b57cec5SDimitry Andric   Terminator.Address = Position.Address;
2070b57cec5SDimitry Andric   Position.Address += Terminator.Size;
2080b57cec5SDimitry Andric   if (AssumeRelaxed)
2090b57cec5SDimitry Andric     Position.Address += Terminator.ExtraRelaxSize;
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric 
212*349cc55cSDimitry Andric static unsigned getInstSizeInBytes(const MachineInstr &MI,
213*349cc55cSDimitry Andric                                    const SystemZInstrInfo *TII) {
214*349cc55cSDimitry Andric   unsigned Size = TII->getInstSizeInBytes(MI);
215*349cc55cSDimitry Andric   assert((Size ||
216*349cc55cSDimitry Andric           // These do not have a size:
217*349cc55cSDimitry Andric           MI.isDebugOrPseudoInstr() || MI.isPosition() || MI.isKill() ||
218*349cc55cSDimitry Andric           MI.isImplicitDef() || MI.getOpcode() == SystemZ::MemBarrier ||
219*349cc55cSDimitry Andric           // These have a size that may be zero:
220*349cc55cSDimitry Andric           MI.isInlineAsm() || MI.getOpcode() == SystemZ::STACKMAP ||
221*349cc55cSDimitry Andric           MI.getOpcode() == SystemZ::PATCHPOINT) &&
222*349cc55cSDimitry Andric          "Missing size value for instruction.");
223*349cc55cSDimitry Andric   return Size;
224*349cc55cSDimitry Andric }
225*349cc55cSDimitry Andric 
2260b57cec5SDimitry Andric // Return a description of terminator instruction MI.
2270b57cec5SDimitry Andric TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr &MI) {
2280b57cec5SDimitry Andric   TerminatorInfo Terminator;
229*349cc55cSDimitry Andric   Terminator.Size = getInstSizeInBytes(MI, TII);
2300b57cec5SDimitry Andric   if (MI.isConditionalBranch() || MI.isUnconditionalBranch()) {
2310b57cec5SDimitry Andric     switch (MI.getOpcode()) {
2320b57cec5SDimitry Andric     case SystemZ::J:
2330b57cec5SDimitry Andric       // Relaxes to JG, which is 2 bytes longer.
2340b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 2;
2350b57cec5SDimitry Andric       break;
2360b57cec5SDimitry Andric     case SystemZ::BRC:
2370b57cec5SDimitry Andric       // Relaxes to BRCL, which is 2 bytes longer.
2380b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 2;
2390b57cec5SDimitry Andric       break;
2400b57cec5SDimitry Andric     case SystemZ::BRCT:
2410b57cec5SDimitry Andric     case SystemZ::BRCTG:
2420b57cec5SDimitry Andric       // Relaxes to A(G)HI and BRCL, which is 6 bytes longer.
2430b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 6;
2440b57cec5SDimitry Andric       break;
2450b57cec5SDimitry Andric     case SystemZ::BRCTH:
2460b57cec5SDimitry Andric       // Never needs to be relaxed.
2470b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 0;
2480b57cec5SDimitry Andric       break;
2490b57cec5SDimitry Andric     case SystemZ::CRJ:
2500b57cec5SDimitry Andric     case SystemZ::CLRJ:
2510b57cec5SDimitry Andric       // Relaxes to a C(L)R/BRCL sequence, which is 2 bytes longer.
2520b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 2;
2530b57cec5SDimitry Andric       break;
2540b57cec5SDimitry Andric     case SystemZ::CGRJ:
2550b57cec5SDimitry Andric     case SystemZ::CLGRJ:
2560b57cec5SDimitry Andric       // Relaxes to a C(L)GR/BRCL sequence, which is 4 bytes longer.
2570b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 4;
2580b57cec5SDimitry Andric       break;
2590b57cec5SDimitry Andric     case SystemZ::CIJ:
2600b57cec5SDimitry Andric     case SystemZ::CGIJ:
2610b57cec5SDimitry Andric       // Relaxes to a C(G)HI/BRCL sequence, which is 4 bytes longer.
2620b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 4;
2630b57cec5SDimitry Andric       break;
2640b57cec5SDimitry Andric     case SystemZ::CLIJ:
2650b57cec5SDimitry Andric     case SystemZ::CLGIJ:
2660b57cec5SDimitry Andric       // Relaxes to a CL(G)FI/BRCL sequence, which is 6 bytes longer.
2670b57cec5SDimitry Andric       Terminator.ExtraRelaxSize = 6;
2680b57cec5SDimitry Andric       break;
2690b57cec5SDimitry Andric     default:
2700b57cec5SDimitry Andric       llvm_unreachable("Unrecognized branch instruction");
2710b57cec5SDimitry Andric     }
2720b57cec5SDimitry Andric     Terminator.Branch = &MI;
2730b57cec5SDimitry Andric     Terminator.TargetBlock =
2740b57cec5SDimitry Andric       TII->getBranchInfo(MI).getMBBTarget()->getNumber();
2750b57cec5SDimitry Andric   }
2760b57cec5SDimitry Andric   return Terminator;
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric // Fill MBBs and Terminators, setting the addresses on the assumption
2800b57cec5SDimitry Andric // that no branches need relaxation.  Return the size of the function under
2810b57cec5SDimitry Andric // this assumption.
2820b57cec5SDimitry Andric uint64_t SystemZLongBranch::initMBBInfo() {
2830b57cec5SDimitry Andric   MF->RenumberBlocks();
2840b57cec5SDimitry Andric   unsigned NumBlocks = MF->size();
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   MBBs.clear();
2870b57cec5SDimitry Andric   MBBs.resize(NumBlocks);
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric   Terminators.clear();
2900b57cec5SDimitry Andric   Terminators.reserve(NumBlocks);
2910b57cec5SDimitry Andric 
2928bcb0991SDimitry Andric   BlockPosition Position(Log2(MF->getAlignment()));
2930b57cec5SDimitry Andric   for (unsigned I = 0; I < NumBlocks; ++I) {
2940b57cec5SDimitry Andric     MachineBasicBlock *MBB = MF->getBlockNumbered(I);
2950b57cec5SDimitry Andric     MBBInfo &Block = MBBs[I];
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric     // Record the alignment, for quick access.
2980b57cec5SDimitry Andric     Block.Alignment = MBB->getAlignment();
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric     // Calculate the size of the fixed part of the block.
3010b57cec5SDimitry Andric     MachineBasicBlock::iterator MI = MBB->begin();
3020b57cec5SDimitry Andric     MachineBasicBlock::iterator End = MBB->end();
3030b57cec5SDimitry Andric     while (MI != End && !MI->isTerminator()) {
304*349cc55cSDimitry Andric       Block.Size += getInstSizeInBytes(*MI, TII);
3050b57cec5SDimitry Andric       ++MI;
3060b57cec5SDimitry Andric     }
3070b57cec5SDimitry Andric     skipNonTerminators(Position, Block);
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric     // Add the terminators.
3100b57cec5SDimitry Andric     while (MI != End) {
3110b57cec5SDimitry Andric       if (!MI->isDebugInstr()) {
3120b57cec5SDimitry Andric         assert(MI->isTerminator() && "Terminator followed by non-terminator");
3130b57cec5SDimitry Andric         Terminators.push_back(describeTerminator(*MI));
3140b57cec5SDimitry Andric         skipTerminator(Position, Terminators.back(), false);
3150b57cec5SDimitry Andric         ++Block.NumTerminators;
3160b57cec5SDimitry Andric       }
3170b57cec5SDimitry Andric       ++MI;
3180b57cec5SDimitry Andric     }
3190b57cec5SDimitry Andric   }
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   return Position.Address;
3220b57cec5SDimitry Andric }
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric // Return true if, under current assumptions, Terminator would need to be
3250b57cec5SDimitry Andric // relaxed if it were placed at address Address.
3260b57cec5SDimitry Andric bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator,
3270b57cec5SDimitry Andric                                         uint64_t Address) {
3280b57cec5SDimitry Andric   if (!Terminator.Branch || Terminator.ExtraRelaxSize == 0)
3290b57cec5SDimitry Andric     return false;
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric   const MBBInfo &Target = MBBs[Terminator.TargetBlock];
3320b57cec5SDimitry Andric   if (Address >= Target.Address) {
3330b57cec5SDimitry Andric     if (Address - Target.Address <= MaxBackwardRange)
3340b57cec5SDimitry Andric       return false;
3350b57cec5SDimitry Andric   } else {
3360b57cec5SDimitry Andric     if (Target.Address - Address <= MaxForwardRange)
3370b57cec5SDimitry Andric       return false;
3380b57cec5SDimitry Andric   }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric   return true;
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric // Return true if, under current assumptions, any terminator needs
3440b57cec5SDimitry Andric // to be relaxed.
3450b57cec5SDimitry Andric bool SystemZLongBranch::mustRelaxABranch() {
3460b57cec5SDimitry Andric   for (auto &Terminator : Terminators)
3470b57cec5SDimitry Andric     if (mustRelaxBranch(Terminator, Terminator.Address))
3480b57cec5SDimitry Andric       return true;
3490b57cec5SDimitry Andric   return false;
3500b57cec5SDimitry Andric }
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric // Set the address of each block on the assumption that all branches
3530b57cec5SDimitry Andric // must be long.
3540b57cec5SDimitry Andric void SystemZLongBranch::setWorstCaseAddresses() {
3550b57cec5SDimitry Andric   SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
3568bcb0991SDimitry Andric   BlockPosition Position(Log2(MF->getAlignment()));
3570b57cec5SDimitry Andric   for (auto &Block : MBBs) {
3580b57cec5SDimitry Andric     skipNonTerminators(Position, Block);
3590b57cec5SDimitry Andric     for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) {
3600b57cec5SDimitry Andric       skipTerminator(Position, *TI, true);
3610b57cec5SDimitry Andric       ++TI;
3620b57cec5SDimitry Andric     }
3630b57cec5SDimitry Andric   }
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric // Split BRANCH ON COUNT MI into the addition given by AddOpcode followed
3670b57cec5SDimitry Andric // by a BRCL on the result.
3680b57cec5SDimitry Andric void SystemZLongBranch::splitBranchOnCount(MachineInstr *MI,
3690b57cec5SDimitry Andric                                            unsigned AddOpcode) {
3700b57cec5SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
3710b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
3720b57cec5SDimitry Andric   BuildMI(*MBB, MI, DL, TII->get(AddOpcode))
3730b57cec5SDimitry Andric       .add(MI->getOperand(0))
3740b57cec5SDimitry Andric       .add(MI->getOperand(1))
3750b57cec5SDimitry Andric       .addImm(-1);
3760b57cec5SDimitry Andric   MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL))
3770b57cec5SDimitry Andric                            .addImm(SystemZ::CCMASK_ICMP)
3780b57cec5SDimitry Andric                            .addImm(SystemZ::CCMASK_CMP_NE)
3790b57cec5SDimitry Andric                            .add(MI->getOperand(2));
3800b57cec5SDimitry Andric   // The implicit use of CC is a killing use.
3810b57cec5SDimitry Andric   BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo());
3820b57cec5SDimitry Andric   MI->eraseFromParent();
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric // Split MI into the comparison given by CompareOpcode followed
3860b57cec5SDimitry Andric // a BRCL on the result.
3870b57cec5SDimitry Andric void SystemZLongBranch::splitCompareBranch(MachineInstr *MI,
3880b57cec5SDimitry Andric                                            unsigned CompareOpcode) {
3890b57cec5SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
3900b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
3910b57cec5SDimitry Andric   BuildMI(*MBB, MI, DL, TII->get(CompareOpcode))
3920b57cec5SDimitry Andric       .add(MI->getOperand(0))
3930b57cec5SDimitry Andric       .add(MI->getOperand(1));
3940b57cec5SDimitry Andric   MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL))
3950b57cec5SDimitry Andric                            .addImm(SystemZ::CCMASK_ICMP)
3960b57cec5SDimitry Andric                            .add(MI->getOperand(2))
3970b57cec5SDimitry Andric                            .add(MI->getOperand(3));
3980b57cec5SDimitry Andric   // The implicit use of CC is a killing use.
3990b57cec5SDimitry Andric   BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo());
4000b57cec5SDimitry Andric   MI->eraseFromParent();
4010b57cec5SDimitry Andric }
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric // Relax the branch described by Terminator.
4040b57cec5SDimitry Andric void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
4050b57cec5SDimitry Andric   MachineInstr *Branch = Terminator.Branch;
4060b57cec5SDimitry Andric   switch (Branch->getOpcode()) {
4070b57cec5SDimitry Andric   case SystemZ::J:
4080b57cec5SDimitry Andric     Branch->setDesc(TII->get(SystemZ::JG));
4090b57cec5SDimitry Andric     break;
4100b57cec5SDimitry Andric   case SystemZ::BRC:
4110b57cec5SDimitry Andric     Branch->setDesc(TII->get(SystemZ::BRCL));
4120b57cec5SDimitry Andric     break;
4130b57cec5SDimitry Andric   case SystemZ::BRCT:
4140b57cec5SDimitry Andric     splitBranchOnCount(Branch, SystemZ::AHI);
4150b57cec5SDimitry Andric     break;
4160b57cec5SDimitry Andric   case SystemZ::BRCTG:
4170b57cec5SDimitry Andric     splitBranchOnCount(Branch, SystemZ::AGHI);
4180b57cec5SDimitry Andric     break;
4190b57cec5SDimitry Andric   case SystemZ::CRJ:
4200b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CR);
4210b57cec5SDimitry Andric     break;
4220b57cec5SDimitry Andric   case SystemZ::CGRJ:
4230b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CGR);
4240b57cec5SDimitry Andric     break;
4250b57cec5SDimitry Andric   case SystemZ::CIJ:
4260b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CHI);
4270b57cec5SDimitry Andric     break;
4280b57cec5SDimitry Andric   case SystemZ::CGIJ:
4290b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CGHI);
4300b57cec5SDimitry Andric     break;
4310b57cec5SDimitry Andric   case SystemZ::CLRJ:
4320b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CLR);
4330b57cec5SDimitry Andric     break;
4340b57cec5SDimitry Andric   case SystemZ::CLGRJ:
4350b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CLGR);
4360b57cec5SDimitry Andric     break;
4370b57cec5SDimitry Andric   case SystemZ::CLIJ:
4380b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CLFI);
4390b57cec5SDimitry Andric     break;
4400b57cec5SDimitry Andric   case SystemZ::CLGIJ:
4410b57cec5SDimitry Andric     splitCompareBranch(Branch, SystemZ::CLGFI);
4420b57cec5SDimitry Andric     break;
4430b57cec5SDimitry Andric   default:
4440b57cec5SDimitry Andric     llvm_unreachable("Unrecognized branch");
4450b57cec5SDimitry Andric   }
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric   Terminator.Size += Terminator.ExtraRelaxSize;
4480b57cec5SDimitry Andric   Terminator.ExtraRelaxSize = 0;
4490b57cec5SDimitry Andric   Terminator.Branch = nullptr;
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric   ++LongBranches;
4520b57cec5SDimitry Andric }
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric // Run a shortening pass and relax any branches that need to be relaxed.
4550b57cec5SDimitry Andric void SystemZLongBranch::relaxBranches() {
4560b57cec5SDimitry Andric   SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
4578bcb0991SDimitry Andric   BlockPosition Position(Log2(MF->getAlignment()));
4580b57cec5SDimitry Andric   for (auto &Block : MBBs) {
4590b57cec5SDimitry Andric     skipNonTerminators(Position, Block);
4600b57cec5SDimitry Andric     for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) {
4610b57cec5SDimitry Andric       assert(Position.Address <= TI->Address &&
4620b57cec5SDimitry Andric              "Addresses shouldn't go forwards");
4630b57cec5SDimitry Andric       if (mustRelaxBranch(*TI, Position.Address))
4640b57cec5SDimitry Andric         relaxBranch(*TI);
4650b57cec5SDimitry Andric       skipTerminator(Position, *TI, false);
4660b57cec5SDimitry Andric       ++TI;
4670b57cec5SDimitry Andric     }
4680b57cec5SDimitry Andric   }
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric bool SystemZLongBranch::runOnMachineFunction(MachineFunction &F) {
4720b57cec5SDimitry Andric   TII = static_cast<const SystemZInstrInfo *>(F.getSubtarget().getInstrInfo());
4730b57cec5SDimitry Andric   MF = &F;
4740b57cec5SDimitry Andric   uint64_t Size = initMBBInfo();
4750b57cec5SDimitry Andric   if (Size <= MaxForwardRange || !mustRelaxABranch())
4760b57cec5SDimitry Andric     return false;
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric   setWorstCaseAddresses();
4790b57cec5SDimitry Andric   relaxBranches();
4800b57cec5SDimitry Andric   return true;
4810b57cec5SDimitry Andric }
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric FunctionPass *llvm::createSystemZLongBranchPass(SystemZTargetMachine &TM) {
4840b57cec5SDimitry Andric   return new SystemZLongBranch(TM);
4850b57cec5SDimitry Andric }
486