1312425f3SRichard Sandiford //===-- SystemZLongBranch.cpp - Branch lengthening for SystemZ ------------===//
2312425f3SRichard Sandiford //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6312425f3SRichard Sandiford //
7312425f3SRichard Sandiford //===----------------------------------------------------------------------===//
8312425f3SRichard Sandiford //
9bdbb8af7SRichard Sandiford // This pass makes sure that all branches are in range.  There are several ways
10bdbb8af7SRichard Sandiford // in which this could be done.  One aggressive approach is to assume that all
11bdbb8af7SRichard Sandiford // branches are in range and successively replace those that turn out not
12bdbb8af7SRichard Sandiford // to be in range with a longer form (branch relaxation).  A simple
13bdbb8af7SRichard Sandiford // implementation is to continually walk through the function relaxing
14bdbb8af7SRichard Sandiford // branches until no more changes are needed and a fixed point is reached.
15bdbb8af7SRichard Sandiford // However, in the pathological worst case, this implementation is
16bdbb8af7SRichard Sandiford // quadratic in the number of blocks; relaxing branch N can make branch N-1
17bdbb8af7SRichard Sandiford // go out of range, which in turn can make branch N-2 go out of range,
18bdbb8af7SRichard Sandiford // and so on.
19312425f3SRichard Sandiford //
20312425f3SRichard Sandiford // An alternative approach is to assume that all branches must be
21312425f3SRichard Sandiford // converted to their long forms, then reinstate the short forms of
22312425f3SRichard Sandiford // branches that, even under this pessimistic assumption, turn out to be
23312425f3SRichard Sandiford // in range (branch shortening).  This too can be implemented as a function
24312425f3SRichard Sandiford // walk that is repeated until a fixed point is reached.  In general,
25312425f3SRichard Sandiford // the result of shortening is not as good as that of relaxation, and
26312425f3SRichard Sandiford // shortening is also quadratic in the worst case; shortening branch N
27312425f3SRichard Sandiford // can bring branch N-1 in range of the short form, which in turn can do
28312425f3SRichard Sandiford // the same for branch N-2, and so on.  The main advantage of shortening
29312425f3SRichard Sandiford // is that each walk through the function produces valid code, so it is
30312425f3SRichard Sandiford // possible to stop at any point after the first walk.  The quadraticness
31312425f3SRichard Sandiford // could therefore be handled with a maximum pass count, although the
32312425f3SRichard Sandiford // question then becomes: what maximum count should be used?
33312425f3SRichard Sandiford //
34312425f3SRichard Sandiford // On SystemZ, long branches are only needed for functions bigger than 64k,
35312425f3SRichard Sandiford // which are relatively rare to begin with, and the long branch sequences
36312425f3SRichard Sandiford // are actually relatively cheap.  It therefore doesn't seem worth spending
37312425f3SRichard Sandiford // much compilation time on the problem.  Instead, the approach we take is:
38312425f3SRichard Sandiford //
3903528f34SRichard Sandiford // (1) Work out the address that each block would have if no branches
4003528f34SRichard Sandiford //     need relaxing.  Exit the pass early if all branches are in range
4103528f34SRichard Sandiford //     according to this assumption.
4203528f34SRichard Sandiford //
4303528f34SRichard Sandiford // (2) Work out the address that each block would have if all branches
4403528f34SRichard Sandiford //     need relaxing.
4503528f34SRichard Sandiford //
4603528f34SRichard Sandiford // (3) Walk through the block calculating the final address of each instruction
4703528f34SRichard Sandiford //     and relaxing those that need to be relaxed.  For backward branches,
4803528f34SRichard Sandiford //     this check uses the final address of the target block, as calculated
4903528f34SRichard Sandiford //     earlier in the walk.  For forward branches, this check uses the
5003528f34SRichard Sandiford //     address of the target block that was calculated in (2).  Both checks
5103528f34SRichard Sandiford //     give a conservatively-correct range.
52312425f3SRichard Sandiford //
53312425f3SRichard Sandiford //===----------------------------------------------------------------------===//
54312425f3SRichard Sandiford 
553943d2b0SEugene Zelenko #include "SystemZ.h"
563943d2b0SEugene Zelenko #include "SystemZInstrInfo.h"
57312425f3SRichard Sandiford #include "SystemZTargetMachine.h"
583943d2b0SEugene Zelenko #include "llvm/ADT/SmallVector.h"
59312425f3SRichard Sandiford #include "llvm/ADT/Statistic.h"
603943d2b0SEugene Zelenko #include "llvm/ADT/StringRef.h"
613943d2b0SEugene Zelenko #include "llvm/CodeGen/MachineBasicBlock.h"
623943d2b0SEugene Zelenko #include "llvm/CodeGen/MachineFunction.h"
63312425f3SRichard Sandiford #include "llvm/CodeGen/MachineFunctionPass.h"
643943d2b0SEugene Zelenko #include "llvm/CodeGen/MachineInstr.h"
65312425f3SRichard Sandiford #include "llvm/CodeGen/MachineInstrBuilder.h"
663943d2b0SEugene Zelenko #include "llvm/IR/DebugLoc.h"
673943d2b0SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
683943d2b0SEugene Zelenko #include <cassert>
693943d2b0SEugene Zelenko #include <cstdint>
70312425f3SRichard Sandiford 
71312425f3SRichard Sandiford using namespace llvm;
72312425f3SRichard Sandiford 
7384e68b29SChandler Carruth #define DEBUG_TYPE "systemz-long-branch"
7484e68b29SChandler Carruth 
75312425f3SRichard Sandiford STATISTIC(LongBranches, "Number of long branches.");
76312425f3SRichard Sandiford 
77312425f3SRichard Sandiford namespace {
783943d2b0SEugene Zelenko 
79312425f3SRichard Sandiford // Represents positional information about a basic block.
80312425f3SRichard Sandiford struct MBBInfo {
8103528f34SRichard Sandiford   // The address that we currently assume the block has.
823943d2b0SEugene Zelenko   uint64_t Address = 0;
83312425f3SRichard Sandiford 
84312425f3SRichard Sandiford   // The size of the block in bytes, excluding terminators.
85312425f3SRichard Sandiford   // This value never changes.
863943d2b0SEugene Zelenko   uint64_t Size = 0;
87312425f3SRichard Sandiford 
88d4c4671aSGuillaume Chatelet   // The minimum alignment of the block.
89312425f3SRichard Sandiford   // This value never changes.
9018f805a7SGuillaume Chatelet   Align Alignment;
91312425f3SRichard Sandiford 
92312425f3SRichard Sandiford   // The number of terminators in this block.  This value never changes.
933943d2b0SEugene Zelenko   unsigned NumTerminators = 0;
94312425f3SRichard Sandiford 
953943d2b0SEugene Zelenko   MBBInfo() = default;
96312425f3SRichard Sandiford };
97312425f3SRichard Sandiford 
98312425f3SRichard Sandiford // Represents the state of a block terminator.
99312425f3SRichard Sandiford struct TerminatorInfo {
100312425f3SRichard Sandiford   // If this terminator is a relaxable branch, this points to the branch
101312425f3SRichard Sandiford   // instruction, otherwise it is null.
1023943d2b0SEugene Zelenko   MachineInstr *Branch = nullptr;
103312425f3SRichard Sandiford 
10403528f34SRichard Sandiford   // The address that we currently assume the terminator has.
1053943d2b0SEugene Zelenko   uint64_t Address = 0;
106312425f3SRichard Sandiford 
107312425f3SRichard Sandiford   // The current size of the terminator in bytes.
1083943d2b0SEugene Zelenko   uint64_t Size = 0;
109312425f3SRichard Sandiford 
110312425f3SRichard Sandiford   // If Branch is nonnull, this is the number of the target block,
111312425f3SRichard Sandiford   // otherwise it is unused.
1123943d2b0SEugene Zelenko   unsigned TargetBlock = 0;
113312425f3SRichard Sandiford 
114312425f3SRichard Sandiford   // If Branch is nonnull, this is the length of the longest relaxed form,
115312425f3SRichard Sandiford   // otherwise it is zero.
1163943d2b0SEugene Zelenko   unsigned ExtraRelaxSize = 0;
117312425f3SRichard Sandiford 
1183943d2b0SEugene Zelenko   TerminatorInfo() = default;
119312425f3SRichard Sandiford };
120312425f3SRichard Sandiford 
121312425f3SRichard Sandiford // Used to keep track of the current position while iterating over the blocks.
122312425f3SRichard Sandiford struct BlockPosition {
12303528f34SRichard Sandiford   // The address that we assume this position has.
1243943d2b0SEugene Zelenko   uint64_t Address = 0;
125312425f3SRichard Sandiford 
126312425f3SRichard Sandiford   // The number of low bits in Address that are known to be the same
127312425f3SRichard Sandiford   // as the runtime address.
128312425f3SRichard Sandiford   unsigned KnownBits;
129312425f3SRichard Sandiford 
BlockPosition__anon9324c0210111::BlockPosition130aff45e4bSGuillaume Chatelet   BlockPosition(unsigned InitialLogAlignment)
131aff45e4bSGuillaume Chatelet       : KnownBits(InitialLogAlignment) {}
132312425f3SRichard Sandiford };
133312425f3SRichard Sandiford 
134312425f3SRichard Sandiford class SystemZLongBranch : public MachineFunctionPass {
135312425f3SRichard Sandiford public:
136312425f3SRichard Sandiford   static char ID;
1373943d2b0SEugene Zelenko 
SystemZLongBranch()138*d5ae039eSKai Nacke   SystemZLongBranch() : MachineFunctionPass(ID) {
139*d5ae039eSKai Nacke     initializeSystemZLongBranchPass(*PassRegistry::getPassRegistry());
140*d5ae039eSKai Nacke   }
141312425f3SRichard Sandiford 
1429d74a5a5SCraig Topper   bool runOnMachineFunction(MachineFunction &F) override;
1433943d2b0SEugene Zelenko 
getRequiredProperties() const1441dbf7a57SDerek Schuff   MachineFunctionProperties getRequiredProperties() const override {
1451dbf7a57SDerek Schuff     return MachineFunctionProperties().set(
1461eb47368SMatthias Braun         MachineFunctionProperties::Property::NoVRegs);
1471dbf7a57SDerek Schuff   }
148312425f3SRichard Sandiford 
149312425f3SRichard Sandiford private:
150312425f3SRichard Sandiford   void skipNonTerminators(BlockPosition &Position, MBBInfo &Block);
151312425f3SRichard Sandiford   void skipTerminator(BlockPosition &Position, TerminatorInfo &Terminator,
152312425f3SRichard Sandiford                       bool AssumeRelaxed);
1539cfc75c2SDuncan P. N. Exon Smith   TerminatorInfo describeTerminator(MachineInstr &MI);
154312425f3SRichard Sandiford   uint64_t initMBBInfo();
15503528f34SRichard Sandiford   bool mustRelaxBranch(const TerminatorInfo &Terminator, uint64_t Address);
156312425f3SRichard Sandiford   bool mustRelaxABranch();
157312425f3SRichard Sandiford   void setWorstCaseAddresses();
158c212125dSRichard Sandiford   void splitBranchOnCount(MachineInstr *MI, unsigned AddOpcode);
1590fb90ab0SRichard Sandiford   void splitCompareBranch(MachineInstr *MI, unsigned CompareOpcode);
160312425f3SRichard Sandiford   void relaxBranch(TerminatorInfo &Terminator);
161312425f3SRichard Sandiford   void relaxBranches();
162312425f3SRichard Sandiford 
1633943d2b0SEugene Zelenko   const SystemZInstrInfo *TII = nullptr;
164e1670175SSimon Pilgrim   MachineFunction *MF = nullptr;
165312425f3SRichard Sandiford   SmallVector<MBBInfo, 16> MBBs;
166312425f3SRichard Sandiford   SmallVector<TerminatorInfo, 16> Terminators;
167312425f3SRichard Sandiford };
168312425f3SRichard Sandiford 
169312425f3SRichard Sandiford char SystemZLongBranch::ID = 0;
170312425f3SRichard Sandiford 
171312425f3SRichard Sandiford const uint64_t MaxBackwardRange = 0x10000;
172312425f3SRichard Sandiford const uint64_t MaxForwardRange = 0xfffe;
173312425f3SRichard Sandiford 
1743943d2b0SEugene Zelenko } // end anonymous namespace
175312425f3SRichard Sandiford 
176*d5ae039eSKai Nacke INITIALIZE_PASS(SystemZLongBranch, DEBUG_TYPE, "SystemZ Long Branch", false,
177*d5ae039eSKai Nacke                 false)
178*d5ae039eSKai Nacke 
179312425f3SRichard Sandiford // Position describes the state immediately before Block.  Update Block
180312425f3SRichard Sandiford // accordingly and move Position to the end of the block's non-terminator
181312425f3SRichard Sandiford // instructions.
skipNonTerminators(BlockPosition & Position,MBBInfo & Block)182312425f3SRichard Sandiford void SystemZLongBranch::skipNonTerminators(BlockPosition &Position,
183312425f3SRichard Sandiford                                            MBBInfo &Block) {
184d4c4671aSGuillaume Chatelet   if (Log2(Block.Alignment) > Position.KnownBits) {
185312425f3SRichard Sandiford     // When calculating the address of Block, we need to conservatively
186312425f3SRichard Sandiford     // assume that Block had the worst possible misalignment.
187d4c4671aSGuillaume Chatelet     Position.Address +=
188d4c4671aSGuillaume Chatelet         (Block.Alignment.value() - (uint64_t(1) << Position.KnownBits));
189d4c4671aSGuillaume Chatelet     Position.KnownBits = Log2(Block.Alignment);
190312425f3SRichard Sandiford   }
191312425f3SRichard Sandiford 
192312425f3SRichard Sandiford   // Align the addresses.
193d4c4671aSGuillaume Chatelet   Position.Address = alignTo(Position.Address, Block.Alignment);
194312425f3SRichard Sandiford 
195312425f3SRichard Sandiford   // Record the block's position.
196312425f3SRichard Sandiford   Block.Address = Position.Address;
197312425f3SRichard Sandiford 
198312425f3SRichard Sandiford   // Move past the non-terminators in the block.
199312425f3SRichard Sandiford   Position.Address += Block.Size;
200312425f3SRichard Sandiford }
201312425f3SRichard Sandiford 
202312425f3SRichard Sandiford // Position describes the state immediately before Terminator.
203312425f3SRichard Sandiford // Update Terminator accordingly and move Position past it.
204312425f3SRichard Sandiford // Assume that Terminator will be relaxed if AssumeRelaxed.
skipTerminator(BlockPosition & Position,TerminatorInfo & Terminator,bool AssumeRelaxed)205312425f3SRichard Sandiford void SystemZLongBranch::skipTerminator(BlockPosition &Position,
206312425f3SRichard Sandiford                                        TerminatorInfo &Terminator,
207312425f3SRichard Sandiford                                        bool AssumeRelaxed) {
208312425f3SRichard Sandiford   Terminator.Address = Position.Address;
209312425f3SRichard Sandiford   Position.Address += Terminator.Size;
210312425f3SRichard Sandiford   if (AssumeRelaxed)
211312425f3SRichard Sandiford     Position.Address += Terminator.ExtraRelaxSize;
212312425f3SRichard Sandiford }
213312425f3SRichard Sandiford 
getInstSizeInBytes(const MachineInstr & MI,const SystemZInstrInfo * TII)2149f887277SJonas Paulsson static unsigned getInstSizeInBytes(const MachineInstr &MI,
2159f887277SJonas Paulsson                                    const SystemZInstrInfo *TII) {
2169f887277SJonas Paulsson   unsigned Size = TII->getInstSizeInBytes(MI);
2179f887277SJonas Paulsson   assert((Size ||
2189f887277SJonas Paulsson           // These do not have a size:
2199f887277SJonas Paulsson           MI.isDebugOrPseudoInstr() || MI.isPosition() || MI.isKill() ||
2209f887277SJonas Paulsson           MI.isImplicitDef() || MI.getOpcode() == SystemZ::MemBarrier ||
2219f887277SJonas Paulsson           // These have a size that may be zero:
2229f887277SJonas Paulsson           MI.isInlineAsm() || MI.getOpcode() == SystemZ::STACKMAP ||
2239f887277SJonas Paulsson           MI.getOpcode() == SystemZ::PATCHPOINT) &&
2249f887277SJonas Paulsson          "Missing size value for instruction.");
2259f887277SJonas Paulsson   return Size;
2269f887277SJonas Paulsson }
2279f887277SJonas Paulsson 
228312425f3SRichard Sandiford // Return a description of terminator instruction MI.
describeTerminator(MachineInstr & MI)2299cfc75c2SDuncan P. N. Exon Smith TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr &MI) {
230312425f3SRichard Sandiford   TerminatorInfo Terminator;
2319f887277SJonas Paulsson   Terminator.Size = getInstSizeInBytes(MI, TII);
2329cfc75c2SDuncan P. N. Exon Smith   if (MI.isConditionalBranch() || MI.isUnconditionalBranch()) {
2339cfc75c2SDuncan P. N. Exon Smith     switch (MI.getOpcode()) {
234312425f3SRichard Sandiford     case SystemZ::J:
235312425f3SRichard Sandiford       // Relaxes to JG, which is 2 bytes longer.
236312425f3SRichard Sandiford       Terminator.ExtraRelaxSize = 2;
237312425f3SRichard Sandiford       break;
238312425f3SRichard Sandiford     case SystemZ::BRC:
23953c9efd9SRichard Sandiford       // Relaxes to BRCL, which is 2 bytes longer.
240312425f3SRichard Sandiford       Terminator.ExtraRelaxSize = 2;
241312425f3SRichard Sandiford       break;
242c212125dSRichard Sandiford     case SystemZ::BRCT:
243c212125dSRichard Sandiford     case SystemZ::BRCTG:
244c212125dSRichard Sandiford       // Relaxes to A(G)HI and BRCL, which is 6 bytes longer.
245c212125dSRichard Sandiford       Terminator.ExtraRelaxSize = 6;
246c212125dSRichard Sandiford       break;
24775839913SUlrich Weigand     case SystemZ::BRCTH:
24875839913SUlrich Weigand       // Never needs to be relaxed.
24975839913SUlrich Weigand       Terminator.ExtraRelaxSize = 0;
25075839913SUlrich Weigand       break;
2510fb90ab0SRichard Sandiford     case SystemZ::CRJ:
25293183ee7SRichard Sandiford     case SystemZ::CLRJ:
25393183ee7SRichard Sandiford       // Relaxes to a C(L)R/BRCL sequence, which is 2 bytes longer.
2540fb90ab0SRichard Sandiford       Terminator.ExtraRelaxSize = 2;
2550fb90ab0SRichard Sandiford       break;
2560fb90ab0SRichard Sandiford     case SystemZ::CGRJ:
25793183ee7SRichard Sandiford     case SystemZ::CLGRJ:
25893183ee7SRichard Sandiford       // Relaxes to a C(L)GR/BRCL sequence, which is 4 bytes longer.
2590fb90ab0SRichard Sandiford       Terminator.ExtraRelaxSize = 4;
2600fb90ab0SRichard Sandiford       break;
261e1d9f00fSRichard Sandiford     case SystemZ::CIJ:
262e1d9f00fSRichard Sandiford     case SystemZ::CGIJ:
263e1d9f00fSRichard Sandiford       // Relaxes to a C(G)HI/BRCL sequence, which is 4 bytes longer.
264e1d9f00fSRichard Sandiford       Terminator.ExtraRelaxSize = 4;
265e1d9f00fSRichard Sandiford       break;
26693183ee7SRichard Sandiford     case SystemZ::CLIJ:
26793183ee7SRichard Sandiford     case SystemZ::CLGIJ:
26893183ee7SRichard Sandiford       // Relaxes to a CL(G)FI/BRCL sequence, which is 6 bytes longer.
26993183ee7SRichard Sandiford       Terminator.ExtraRelaxSize = 6;
27093183ee7SRichard Sandiford       break;
271312425f3SRichard Sandiford     default:
272312425f3SRichard Sandiford       llvm_unreachable("Unrecognized branch instruction");
273312425f3SRichard Sandiford     }
2749cfc75c2SDuncan P. N. Exon Smith     Terminator.Branch = &MI;
27553c9efd9SRichard Sandiford     Terminator.TargetBlock =
27682185878SJonas Paulsson       TII->getBranchInfo(MI).getMBBTarget()->getNumber();
277312425f3SRichard Sandiford   }
278312425f3SRichard Sandiford   return Terminator;
279312425f3SRichard Sandiford }
280312425f3SRichard Sandiford 
281312425f3SRichard Sandiford // Fill MBBs and Terminators, setting the addresses on the assumption
282312425f3SRichard Sandiford // that no branches need relaxation.  Return the size of the function under
283312425f3SRichard Sandiford // this assumption.
initMBBInfo()284312425f3SRichard Sandiford uint64_t SystemZLongBranch::initMBBInfo() {
285312425f3SRichard Sandiford   MF->RenumberBlocks();
286312425f3SRichard Sandiford   unsigned NumBlocks = MF->size();
287312425f3SRichard Sandiford 
288312425f3SRichard Sandiford   MBBs.clear();
289312425f3SRichard Sandiford   MBBs.resize(NumBlocks);
290312425f3SRichard Sandiford 
291312425f3SRichard Sandiford   Terminators.clear();
292312425f3SRichard Sandiford   Terminators.reserve(NumBlocks);
293312425f3SRichard Sandiford 
29448904e94SGuillaume Chatelet   BlockPosition Position(Log2(MF->getAlignment()));
295312425f3SRichard Sandiford   for (unsigned I = 0; I < NumBlocks; ++I) {
296312425f3SRichard Sandiford     MachineBasicBlock *MBB = MF->getBlockNumbered(I);
297312425f3SRichard Sandiford     MBBInfo &Block = MBBs[I];
298312425f3SRichard Sandiford 
299312425f3SRichard Sandiford     // Record the alignment, for quick access.
300d4c4671aSGuillaume Chatelet     Block.Alignment = MBB->getAlignment();
301312425f3SRichard Sandiford 
302312425f3SRichard Sandiford     // Calculate the size of the fixed part of the block.
303312425f3SRichard Sandiford     MachineBasicBlock::iterator MI = MBB->begin();
304312425f3SRichard Sandiford     MachineBasicBlock::iterator End = MBB->end();
305312425f3SRichard Sandiford     while (MI != End && !MI->isTerminator()) {
3069f887277SJonas Paulsson       Block.Size += getInstSizeInBytes(*MI, TII);
307312425f3SRichard Sandiford       ++MI;
308312425f3SRichard Sandiford     }
309312425f3SRichard Sandiford     skipNonTerminators(Position, Block);
310312425f3SRichard Sandiford 
311312425f3SRichard Sandiford     // Add the terminators.
312312425f3SRichard Sandiford     while (MI != End) {
313801bf7ebSShiva Chen       if (!MI->isDebugInstr()) {
314312425f3SRichard Sandiford         assert(MI->isTerminator() && "Terminator followed by non-terminator");
3159cfc75c2SDuncan P. N. Exon Smith         Terminators.push_back(describeTerminator(*MI));
316312425f3SRichard Sandiford         skipTerminator(Position, Terminators.back(), false);
317312425f3SRichard Sandiford         ++Block.NumTerminators;
318312425f3SRichard Sandiford       }
319312425f3SRichard Sandiford       ++MI;
320312425f3SRichard Sandiford     }
321312425f3SRichard Sandiford   }
322312425f3SRichard Sandiford 
323312425f3SRichard Sandiford   return Position.Address;
324312425f3SRichard Sandiford }
325312425f3SRichard Sandiford 
32603528f34SRichard Sandiford // Return true if, under current assumptions, Terminator would need to be
32703528f34SRichard Sandiford // relaxed if it were placed at address Address.
mustRelaxBranch(const TerminatorInfo & Terminator,uint64_t Address)32803528f34SRichard Sandiford bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator,
32903528f34SRichard Sandiford                                         uint64_t Address) {
330ef785694SJonas Paulsson   if (!Terminator.Branch || Terminator.ExtraRelaxSize == 0)
331312425f3SRichard Sandiford     return false;
332312425f3SRichard Sandiford 
333312425f3SRichard Sandiford   const MBBInfo &Target = MBBs[Terminator.TargetBlock];
33403528f34SRichard Sandiford   if (Address >= Target.Address) {
33503528f34SRichard Sandiford     if (Address - Target.Address <= MaxBackwardRange)
336312425f3SRichard Sandiford       return false;
337312425f3SRichard Sandiford   } else {
33803528f34SRichard Sandiford     if (Target.Address - Address <= MaxForwardRange)
339312425f3SRichard Sandiford       return false;
340312425f3SRichard Sandiford   }
341312425f3SRichard Sandiford 
342312425f3SRichard Sandiford   return true;
343312425f3SRichard Sandiford }
344312425f3SRichard Sandiford 
345312425f3SRichard Sandiford // Return true if, under current assumptions, any terminator needs
346312425f3SRichard Sandiford // to be relaxed.
mustRelaxABranch()347312425f3SRichard Sandiford bool SystemZLongBranch::mustRelaxABranch() {
34828c111ecSRichard Sandiford   for (auto &Terminator : Terminators)
34928c111ecSRichard Sandiford     if (mustRelaxBranch(Terminator, Terminator.Address))
350312425f3SRichard Sandiford       return true;
351312425f3SRichard Sandiford   return false;
352312425f3SRichard Sandiford }
353312425f3SRichard Sandiford 
354312425f3SRichard Sandiford // Set the address of each block on the assumption that all branches
355312425f3SRichard Sandiford // must be long.
setWorstCaseAddresses()356312425f3SRichard Sandiford void SystemZLongBranch::setWorstCaseAddresses() {
357312425f3SRichard Sandiford   SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
35848904e94SGuillaume Chatelet   BlockPosition Position(Log2(MF->getAlignment()));
35928c111ecSRichard Sandiford   for (auto &Block : MBBs) {
36028c111ecSRichard Sandiford     skipNonTerminators(Position, Block);
36128c111ecSRichard Sandiford     for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) {
362312425f3SRichard Sandiford       skipTerminator(Position, *TI, true);
363312425f3SRichard Sandiford       ++TI;
364312425f3SRichard Sandiford     }
365312425f3SRichard Sandiford   }
366312425f3SRichard Sandiford }
367312425f3SRichard Sandiford 
368c212125dSRichard Sandiford // Split BRANCH ON COUNT MI into the addition given by AddOpcode followed
369c212125dSRichard Sandiford // by a BRCL on the result.
splitBranchOnCount(MachineInstr * MI,unsigned AddOpcode)370c212125dSRichard Sandiford void SystemZLongBranch::splitBranchOnCount(MachineInstr *MI,
371c212125dSRichard Sandiford                                            unsigned AddOpcode) {
372c212125dSRichard Sandiford   MachineBasicBlock *MBB = MI->getParent();
373c212125dSRichard Sandiford   DebugLoc DL = MI->getDebugLoc();
374c212125dSRichard Sandiford   BuildMI(*MBB, MI, DL, TII->get(AddOpcode))
375116bbab4SDiana Picus       .add(MI->getOperand(0))
376116bbab4SDiana Picus       .add(MI->getOperand(1))
377c212125dSRichard Sandiford       .addImm(-1);
378c212125dSRichard Sandiford   MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL))
379c212125dSRichard Sandiford                            .addImm(SystemZ::CCMASK_ICMP)
380c212125dSRichard Sandiford                            .addImm(SystemZ::CCMASK_CMP_NE)
381116bbab4SDiana Picus                            .add(MI->getOperand(2));
382c212125dSRichard Sandiford   // The implicit use of CC is a killing use.
383c212125dSRichard Sandiford   BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo());
384c212125dSRichard Sandiford   MI->eraseFromParent();
385c212125dSRichard Sandiford }
386c212125dSRichard Sandiford 
3870fb90ab0SRichard Sandiford // Split MI into the comparison given by CompareOpcode followed
3880fb90ab0SRichard Sandiford // a BRCL on the result.
splitCompareBranch(MachineInstr * MI,unsigned CompareOpcode)3890fb90ab0SRichard Sandiford void SystemZLongBranch::splitCompareBranch(MachineInstr *MI,
3900fb90ab0SRichard Sandiford                                            unsigned CompareOpcode) {
3910fb90ab0SRichard Sandiford   MachineBasicBlock *MBB = MI->getParent();
3920fb90ab0SRichard Sandiford   DebugLoc DL = MI->getDebugLoc();
3930fb90ab0SRichard Sandiford   BuildMI(*MBB, MI, DL, TII->get(CompareOpcode))
394116bbab4SDiana Picus       .add(MI->getOperand(0))
395116bbab4SDiana Picus       .add(MI->getOperand(1));
3960fb90ab0SRichard Sandiford   MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL))
3973d768e33SRichard Sandiford                            .addImm(SystemZ::CCMASK_ICMP)
398116bbab4SDiana Picus                            .add(MI->getOperand(2))
399116bbab4SDiana Picus                            .add(MI->getOperand(3));
4000fb90ab0SRichard Sandiford   // The implicit use of CC is a killing use.
4013d768e33SRichard Sandiford   BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo());
4020fb90ab0SRichard Sandiford   MI->eraseFromParent();
4030fb90ab0SRichard Sandiford }
4040fb90ab0SRichard Sandiford 
405312425f3SRichard Sandiford // Relax the branch described by Terminator.
relaxBranch(TerminatorInfo & Terminator)406312425f3SRichard Sandiford void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
407312425f3SRichard Sandiford   MachineInstr *Branch = Terminator.Branch;
408312425f3SRichard Sandiford   switch (Branch->getOpcode()) {
409312425f3SRichard Sandiford   case SystemZ::J:
410312425f3SRichard Sandiford     Branch->setDesc(TII->get(SystemZ::JG));
411312425f3SRichard Sandiford     break;
412312425f3SRichard Sandiford   case SystemZ::BRC:
413312425f3SRichard Sandiford     Branch->setDesc(TII->get(SystemZ::BRCL));
414312425f3SRichard Sandiford     break;
415c212125dSRichard Sandiford   case SystemZ::BRCT:
416c212125dSRichard Sandiford     splitBranchOnCount(Branch, SystemZ::AHI);
417c212125dSRichard Sandiford     break;
418c212125dSRichard Sandiford   case SystemZ::BRCTG:
419c212125dSRichard Sandiford     splitBranchOnCount(Branch, SystemZ::AGHI);
420c212125dSRichard Sandiford     break;
4210fb90ab0SRichard Sandiford   case SystemZ::CRJ:
4220fb90ab0SRichard Sandiford     splitCompareBranch(Branch, SystemZ::CR);
4230fb90ab0SRichard Sandiford     break;
4240fb90ab0SRichard Sandiford   case SystemZ::CGRJ:
4250fb90ab0SRichard Sandiford     splitCompareBranch(Branch, SystemZ::CGR);
4260fb90ab0SRichard Sandiford     break;
427e1d9f00fSRichard Sandiford   case SystemZ::CIJ:
428e1d9f00fSRichard Sandiford     splitCompareBranch(Branch, SystemZ::CHI);
429e1d9f00fSRichard Sandiford     break;
430e1d9f00fSRichard Sandiford   case SystemZ::CGIJ:
431e1d9f00fSRichard Sandiford     splitCompareBranch(Branch, SystemZ::CGHI);
432e1d9f00fSRichard Sandiford     break;
43393183ee7SRichard Sandiford   case SystemZ::CLRJ:
43493183ee7SRichard Sandiford     splitCompareBranch(Branch, SystemZ::CLR);
43593183ee7SRichard Sandiford     break;
43693183ee7SRichard Sandiford   case SystemZ::CLGRJ:
43793183ee7SRichard Sandiford     splitCompareBranch(Branch, SystemZ::CLGR);
43893183ee7SRichard Sandiford     break;
43993183ee7SRichard Sandiford   case SystemZ::CLIJ:
44093183ee7SRichard Sandiford     splitCompareBranch(Branch, SystemZ::CLFI);
44193183ee7SRichard Sandiford     break;
44293183ee7SRichard Sandiford   case SystemZ::CLGIJ:
44393183ee7SRichard Sandiford     splitCompareBranch(Branch, SystemZ::CLGFI);
44493183ee7SRichard Sandiford     break;
445312425f3SRichard Sandiford   default:
446312425f3SRichard Sandiford     llvm_unreachable("Unrecognized branch");
447312425f3SRichard Sandiford   }
448312425f3SRichard Sandiford 
449312425f3SRichard Sandiford   Terminator.Size += Terminator.ExtraRelaxSize;
450312425f3SRichard Sandiford   Terminator.ExtraRelaxSize = 0;
451062a2baeSCraig Topper   Terminator.Branch = nullptr;
452312425f3SRichard Sandiford 
453312425f3SRichard Sandiford   ++LongBranches;
454312425f3SRichard Sandiford }
455312425f3SRichard Sandiford 
45603528f34SRichard Sandiford // Run a shortening pass and relax any branches that need to be relaxed.
relaxBranches()457312425f3SRichard Sandiford void SystemZLongBranch::relaxBranches() {
45803528f34SRichard Sandiford   SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
45948904e94SGuillaume Chatelet   BlockPosition Position(Log2(MF->getAlignment()));
46028c111ecSRichard Sandiford   for (auto &Block : MBBs) {
46128c111ecSRichard Sandiford     skipNonTerminators(Position, Block);
46228c111ecSRichard Sandiford     for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) {
46303528f34SRichard Sandiford       assert(Position.Address <= TI->Address &&
46403528f34SRichard Sandiford              "Addresses shouldn't go forwards");
46503528f34SRichard Sandiford       if (mustRelaxBranch(*TI, Position.Address))
466312425f3SRichard Sandiford         relaxBranch(*TI);
46703528f34SRichard Sandiford       skipTerminator(Position, *TI, false);
46803528f34SRichard Sandiford       ++TI;
46903528f34SRichard Sandiford     }
47003528f34SRichard Sandiford   }
471312425f3SRichard Sandiford }
472312425f3SRichard Sandiford 
runOnMachineFunction(MachineFunction & F)473312425f3SRichard Sandiford bool SystemZLongBranch::runOnMachineFunction(MachineFunction &F) {
474fc6de428SEric Christopher   TII = static_cast<const SystemZInstrInfo *>(F.getSubtarget().getInstrInfo());
475312425f3SRichard Sandiford   MF = &F;
476312425f3SRichard Sandiford   uint64_t Size = initMBBInfo();
477312425f3SRichard Sandiford   if (Size <= MaxForwardRange || !mustRelaxABranch())
478312425f3SRichard Sandiford     return false;
479312425f3SRichard Sandiford 
480312425f3SRichard Sandiford   setWorstCaseAddresses();
481312425f3SRichard Sandiford   relaxBranches();
482312425f3SRichard Sandiford   return true;
483312425f3SRichard Sandiford }
4843943d2b0SEugene Zelenko 
createSystemZLongBranchPass(SystemZTargetMachine & TM)4853943d2b0SEugene Zelenko FunctionPass *llvm::createSystemZLongBranchPass(SystemZTargetMachine &TM) {
486*d5ae039eSKai Nacke   return new SystemZLongBranch();
4873943d2b0SEugene Zelenko }
488