1f785676fSDimitry Andric //===-- SystemZLongBranch.cpp - Branch lengthening for SystemZ ------------===//
2f785676fSDimitry Andric //
3f785676fSDimitry Andric //                     The LLVM Compiler Infrastructure
4f785676fSDimitry Andric //
5f785676fSDimitry Andric // This file is distributed under the University of Illinois Open Source
6f785676fSDimitry Andric // License. See LICENSE.TXT for details.
7f785676fSDimitry Andric //
8f785676fSDimitry Andric //===----------------------------------------------------------------------===//
9f785676fSDimitry Andric //
10f785676fSDimitry Andric // This pass makes sure that all branches are in range.  There are several ways
11f785676fSDimitry Andric // in which this could be done.  One aggressive approach is to assume that all
12f785676fSDimitry Andric // branches are in range and successively replace those that turn out not
13f785676fSDimitry Andric // to be in range with a longer form (branch relaxation).  A simple
14f785676fSDimitry Andric // implementation is to continually walk through the function relaxing
15f785676fSDimitry Andric // branches until no more changes are needed and a fixed point is reached.
16f785676fSDimitry Andric // However, in the pathological worst case, this implementation is
17f785676fSDimitry Andric // quadratic in the number of blocks; relaxing branch N can make branch N-1
18f785676fSDimitry Andric // go out of range, which in turn can make branch N-2 go out of range,
19f785676fSDimitry Andric // and so on.
20f785676fSDimitry Andric //
21f785676fSDimitry Andric // An alternative approach is to assume that all branches must be
22f785676fSDimitry Andric // converted to their long forms, then reinstate the short forms of
23f785676fSDimitry Andric // branches that, even under this pessimistic assumption, turn out to be
24f785676fSDimitry Andric // in range (branch shortening).  This too can be implemented as a function
25f785676fSDimitry Andric // walk that is repeated until a fixed point is reached.  In general,
26f785676fSDimitry Andric // the result of shortening is not as good as that of relaxation, and
27f785676fSDimitry Andric // shortening is also quadratic in the worst case; shortening branch N
28f785676fSDimitry Andric // can bring branch N-1 in range of the short form, which in turn can do
29f785676fSDimitry Andric // the same for branch N-2, and so on.  The main advantage of shortening
30f785676fSDimitry Andric // is that each walk through the function produces valid code, so it is
31f785676fSDimitry Andric // possible to stop at any point after the first walk.  The quadraticness
32f785676fSDimitry Andric // could therefore be handled with a maximum pass count, although the
33f785676fSDimitry Andric // question then becomes: what maximum count should be used?
34f785676fSDimitry Andric //
35f785676fSDimitry Andric // On SystemZ, long branches are only needed for functions bigger than 64k,
36f785676fSDimitry Andric // which are relatively rare to begin with, and the long branch sequences
37f785676fSDimitry Andric // are actually relatively cheap.  It therefore doesn't seem worth spending
38f785676fSDimitry Andric // much compilation time on the problem.  Instead, the approach we take is:
39f785676fSDimitry Andric //
40f785676fSDimitry Andric // (1) Work out the address that each block would have if no branches
41f785676fSDimitry Andric //     need relaxing.  Exit the pass early if all branches are in range
42f785676fSDimitry Andric //     according to this assumption.
43f785676fSDimitry Andric //
44f785676fSDimitry Andric // (2) Work out the address that each block would have if all branches
45f785676fSDimitry Andric //     need relaxing.
46f785676fSDimitry Andric //
47f785676fSDimitry Andric // (3) Walk through the block calculating the final address of each instruction
48f785676fSDimitry Andric //     and relaxing those that need to be relaxed.  For backward branches,
49f785676fSDimitry Andric //     this check uses the final address of the target block, as calculated
50f785676fSDimitry Andric //     earlier in the walk.  For forward branches, this check uses the
51f785676fSDimitry Andric //     address of the target block that was calculated in (2).  Both checks
52f785676fSDimitry Andric //     give a conservatively-correct range.
53f785676fSDimitry Andric //
54f785676fSDimitry Andric //===----------------------------------------------------------------------===//
55f785676fSDimitry Andric 
567a7e6055SDimitry Andric #include "SystemZ.h"
577a7e6055SDimitry Andric #include "SystemZInstrInfo.h"
58f785676fSDimitry Andric #include "SystemZTargetMachine.h"
597a7e6055SDimitry Andric #include "llvm/ADT/SmallVector.h"
60f785676fSDimitry Andric #include "llvm/ADT/Statistic.h"
617a7e6055SDimitry Andric #include "llvm/ADT/StringRef.h"
627a7e6055SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
637a7e6055SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
64f785676fSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
657a7e6055SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
66f785676fSDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
677a7e6055SDimitry Andric #include "llvm/IR/DebugLoc.h"
687a7e6055SDimitry Andric #include "llvm/Support/ErrorHandling.h"
697a7e6055SDimitry Andric #include <cassert>
707a7e6055SDimitry Andric #include <cstdint>
71f785676fSDimitry Andric 
72f785676fSDimitry Andric using namespace llvm;
73f785676fSDimitry Andric 
7491bc56edSDimitry Andric #define DEBUG_TYPE "systemz-long-branch"
7591bc56edSDimitry Andric 
76f785676fSDimitry Andric STATISTIC(LongBranches, "Number of long branches.");
77f785676fSDimitry Andric 
78f785676fSDimitry Andric namespace {
797a7e6055SDimitry Andric 
80f785676fSDimitry Andric // Represents positional information about a basic block.
81f785676fSDimitry Andric struct MBBInfo {
82f785676fSDimitry Andric   // The address that we currently assume the block has.
837a7e6055SDimitry Andric   uint64_t Address = 0;
84f785676fSDimitry Andric 
85f785676fSDimitry Andric   // The size of the block in bytes, excluding terminators.
86f785676fSDimitry Andric   // This value never changes.
877a7e6055SDimitry Andric   uint64_t Size = 0;
88f785676fSDimitry Andric 
89f785676fSDimitry Andric   // The minimum alignment of the block, as a log2 value.
90f785676fSDimitry Andric   // This value never changes.
917a7e6055SDimitry Andric   unsigned Alignment = 0;
92f785676fSDimitry Andric 
93f785676fSDimitry Andric   // The number of terminators in this block.  This value never changes.
947a7e6055SDimitry Andric   unsigned NumTerminators = 0;
95f785676fSDimitry Andric 
967a7e6055SDimitry Andric   MBBInfo() = default;
97f785676fSDimitry Andric };
98f785676fSDimitry Andric 
99f785676fSDimitry Andric // Represents the state of a block terminator.
100f785676fSDimitry Andric struct TerminatorInfo {
101f785676fSDimitry Andric   // If this terminator is a relaxable branch, this points to the branch
102f785676fSDimitry Andric   // instruction, otherwise it is null.
1037a7e6055SDimitry Andric   MachineInstr *Branch = nullptr;
104f785676fSDimitry Andric 
105f785676fSDimitry Andric   // The address that we currently assume the terminator has.
1067a7e6055SDimitry Andric   uint64_t Address = 0;
107f785676fSDimitry Andric 
108f785676fSDimitry Andric   // The current size of the terminator in bytes.
1097a7e6055SDimitry Andric   uint64_t Size = 0;
110f785676fSDimitry Andric 
111f785676fSDimitry Andric   // If Branch is nonnull, this is the number of the target block,
112f785676fSDimitry Andric   // otherwise it is unused.
1137a7e6055SDimitry Andric   unsigned TargetBlock = 0;
114f785676fSDimitry Andric 
115f785676fSDimitry Andric   // If Branch is nonnull, this is the length of the longest relaxed form,
116f785676fSDimitry Andric   // otherwise it is zero.
1177a7e6055SDimitry Andric   unsigned ExtraRelaxSize = 0;
118f785676fSDimitry Andric 
1197a7e6055SDimitry Andric   TerminatorInfo() = default;
120f785676fSDimitry Andric };
121f785676fSDimitry Andric 
122f785676fSDimitry Andric // Used to keep track of the current position while iterating over the blocks.
123f785676fSDimitry Andric struct BlockPosition {
124f785676fSDimitry Andric   // The address that we assume this position has.
1257a7e6055SDimitry Andric   uint64_t Address = 0;
126f785676fSDimitry Andric 
127f785676fSDimitry Andric   // The number of low bits in Address that are known to be the same
128f785676fSDimitry Andric   // as the runtime address.
129f785676fSDimitry Andric   unsigned KnownBits;
130f785676fSDimitry Andric 
BlockPosition__anon42215d160111::BlockPosition1317a7e6055SDimitry Andric   BlockPosition(unsigned InitialAlignment) : KnownBits(InitialAlignment) {}
132f785676fSDimitry Andric };
133f785676fSDimitry Andric 
134f785676fSDimitry Andric class SystemZLongBranch : public MachineFunctionPass {
135f785676fSDimitry Andric public:
136f785676fSDimitry Andric   static char ID;
1377a7e6055SDimitry Andric 
SystemZLongBranch(const SystemZTargetMachine & tm)138f785676fSDimitry Andric   SystemZLongBranch(const SystemZTargetMachine &tm)
1397a7e6055SDimitry Andric     : MachineFunctionPass(ID) {}
140f785676fSDimitry Andric 
getPassName() const141d88c1a5aSDimitry Andric   StringRef getPassName() const override { return "SystemZ Long Branch"; }
142f785676fSDimitry Andric 
14391bc56edSDimitry Andric   bool runOnMachineFunction(MachineFunction &F) override;
1447a7e6055SDimitry Andric 
getRequiredProperties() const1453ca95b02SDimitry Andric   MachineFunctionProperties getRequiredProperties() const override {
1463ca95b02SDimitry Andric     return MachineFunctionProperties().set(
147d88c1a5aSDimitry Andric         MachineFunctionProperties::Property::NoVRegs);
1483ca95b02SDimitry Andric   }
149f785676fSDimitry Andric 
150f785676fSDimitry Andric private:
151f785676fSDimitry Andric   void skipNonTerminators(BlockPosition &Position, MBBInfo &Block);
152f785676fSDimitry Andric   void skipTerminator(BlockPosition &Position, TerminatorInfo &Terminator,
153f785676fSDimitry Andric                       bool AssumeRelaxed);
1543ca95b02SDimitry Andric   TerminatorInfo describeTerminator(MachineInstr &MI);
155f785676fSDimitry Andric   uint64_t initMBBInfo();
156f785676fSDimitry Andric   bool mustRelaxBranch(const TerminatorInfo &Terminator, uint64_t Address);
157f785676fSDimitry Andric   bool mustRelaxABranch();
158f785676fSDimitry Andric   void setWorstCaseAddresses();
159f785676fSDimitry Andric   void splitBranchOnCount(MachineInstr *MI, unsigned AddOpcode);
160f785676fSDimitry Andric   void splitCompareBranch(MachineInstr *MI, unsigned CompareOpcode);
161f785676fSDimitry Andric   void relaxBranch(TerminatorInfo &Terminator);
162f785676fSDimitry Andric   void relaxBranches();
163f785676fSDimitry Andric 
1647a7e6055SDimitry Andric   const SystemZInstrInfo *TII = nullptr;
165f785676fSDimitry Andric   MachineFunction *MF;
166f785676fSDimitry Andric   SmallVector<MBBInfo, 16> MBBs;
167f785676fSDimitry Andric   SmallVector<TerminatorInfo, 16> Terminators;
168f785676fSDimitry Andric };
169f785676fSDimitry Andric 
170f785676fSDimitry Andric char SystemZLongBranch::ID = 0;
171f785676fSDimitry Andric 
172f785676fSDimitry Andric const uint64_t MaxBackwardRange = 0x10000;
173f785676fSDimitry Andric const uint64_t MaxForwardRange = 0xfffe;
174f785676fSDimitry Andric 
1757a7e6055SDimitry Andric } // end anonymous namespace
176f785676fSDimitry Andric 
177f785676fSDimitry Andric // Position describes the state immediately before Block.  Update Block
178f785676fSDimitry Andric // accordingly and move Position to the end of the block's non-terminator
179f785676fSDimitry Andric // instructions.
skipNonTerminators(BlockPosition & Position,MBBInfo & Block)180f785676fSDimitry Andric void SystemZLongBranch::skipNonTerminators(BlockPosition &Position,
181f785676fSDimitry Andric                                            MBBInfo &Block) {
182f785676fSDimitry Andric   if (Block.Alignment > Position.KnownBits) {
183f785676fSDimitry Andric     // When calculating the address of Block, we need to conservatively
184f785676fSDimitry Andric     // assume that Block had the worst possible misalignment.
185f785676fSDimitry Andric     Position.Address += ((uint64_t(1) << Block.Alignment) -
186f785676fSDimitry Andric                          (uint64_t(1) << Position.KnownBits));
187f785676fSDimitry Andric     Position.KnownBits = Block.Alignment;
188f785676fSDimitry Andric   }
189f785676fSDimitry Andric 
190f785676fSDimitry Andric   // Align the addresses.
191f785676fSDimitry Andric   uint64_t AlignMask = (uint64_t(1) << Block.Alignment) - 1;
192f785676fSDimitry Andric   Position.Address = (Position.Address + AlignMask) & ~AlignMask;
193f785676fSDimitry Andric 
194f785676fSDimitry Andric   // Record the block's position.
195f785676fSDimitry Andric   Block.Address = Position.Address;
196f785676fSDimitry Andric 
197f785676fSDimitry Andric   // Move past the non-terminators in the block.
198f785676fSDimitry Andric   Position.Address += Block.Size;
199f785676fSDimitry Andric }
200f785676fSDimitry Andric 
201f785676fSDimitry Andric // Position describes the state immediately before Terminator.
202f785676fSDimitry Andric // Update Terminator accordingly and move Position past it.
203f785676fSDimitry Andric // Assume that Terminator will be relaxed if AssumeRelaxed.
skipTerminator(BlockPosition & Position,TerminatorInfo & Terminator,bool AssumeRelaxed)204f785676fSDimitry Andric void SystemZLongBranch::skipTerminator(BlockPosition &Position,
205f785676fSDimitry Andric                                        TerminatorInfo &Terminator,
206f785676fSDimitry Andric                                        bool AssumeRelaxed) {
207f785676fSDimitry Andric   Terminator.Address = Position.Address;
208f785676fSDimitry Andric   Position.Address += Terminator.Size;
209f785676fSDimitry Andric   if (AssumeRelaxed)
210f785676fSDimitry Andric     Position.Address += Terminator.ExtraRelaxSize;
211f785676fSDimitry Andric }
212f785676fSDimitry Andric 
213f785676fSDimitry Andric // Return a description of terminator instruction MI.
describeTerminator(MachineInstr & MI)2143ca95b02SDimitry Andric TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr &MI) {
215f785676fSDimitry Andric   TerminatorInfo Terminator;
216f785676fSDimitry Andric   Terminator.Size = TII->getInstSizeInBytes(MI);
2173ca95b02SDimitry Andric   if (MI.isConditionalBranch() || MI.isUnconditionalBranch()) {
2183ca95b02SDimitry Andric     switch (MI.getOpcode()) {
219f785676fSDimitry Andric     case SystemZ::J:
220f785676fSDimitry Andric       // Relaxes to JG, which is 2 bytes longer.
221f785676fSDimitry Andric       Terminator.ExtraRelaxSize = 2;
222f785676fSDimitry Andric       break;
223f785676fSDimitry Andric     case SystemZ::BRC:
224f785676fSDimitry Andric       // Relaxes to BRCL, which is 2 bytes longer.
225f785676fSDimitry Andric       Terminator.ExtraRelaxSize = 2;
226f785676fSDimitry Andric       break;
227f785676fSDimitry Andric     case SystemZ::BRCT:
228f785676fSDimitry Andric     case SystemZ::BRCTG:
229f785676fSDimitry Andric       // Relaxes to A(G)HI and BRCL, which is 6 bytes longer.
230f785676fSDimitry Andric       Terminator.ExtraRelaxSize = 6;
231f785676fSDimitry Andric       break;
232d88c1a5aSDimitry Andric     case SystemZ::BRCTH:
233d88c1a5aSDimitry Andric       // Never needs to be relaxed.
234d88c1a5aSDimitry Andric       Terminator.ExtraRelaxSize = 0;
235d88c1a5aSDimitry Andric       break;
236f785676fSDimitry Andric     case SystemZ::CRJ:
237f785676fSDimitry Andric     case SystemZ::CLRJ:
238f785676fSDimitry Andric       // Relaxes to a C(L)R/BRCL sequence, which is 2 bytes longer.
239f785676fSDimitry Andric       Terminator.ExtraRelaxSize = 2;
240f785676fSDimitry Andric       break;
241f785676fSDimitry Andric     case SystemZ::CGRJ:
242f785676fSDimitry Andric     case SystemZ::CLGRJ:
243f785676fSDimitry Andric       // Relaxes to a C(L)GR/BRCL sequence, which is 4 bytes longer.
244f785676fSDimitry Andric       Terminator.ExtraRelaxSize = 4;
245f785676fSDimitry Andric       break;
246f785676fSDimitry Andric     case SystemZ::CIJ:
247f785676fSDimitry Andric     case SystemZ::CGIJ:
248f785676fSDimitry Andric       // Relaxes to a C(G)HI/BRCL sequence, which is 4 bytes longer.
249f785676fSDimitry Andric       Terminator.ExtraRelaxSize = 4;
250f785676fSDimitry Andric       break;
251f785676fSDimitry Andric     case SystemZ::CLIJ:
252f785676fSDimitry Andric     case SystemZ::CLGIJ:
253f785676fSDimitry Andric       // Relaxes to a CL(G)FI/BRCL sequence, which is 6 bytes longer.
254f785676fSDimitry Andric       Terminator.ExtraRelaxSize = 6;
255f785676fSDimitry Andric       break;
256f785676fSDimitry Andric     default:
257f785676fSDimitry Andric       llvm_unreachable("Unrecognized branch instruction");
258f785676fSDimitry Andric     }
2593ca95b02SDimitry Andric     Terminator.Branch = &MI;
260f785676fSDimitry Andric     Terminator.TargetBlock =
261f785676fSDimitry Andric       TII->getBranchInfo(MI).Target->getMBB()->getNumber();
262f785676fSDimitry Andric   }
263f785676fSDimitry Andric   return Terminator;
264f785676fSDimitry Andric }
265f785676fSDimitry Andric 
266f785676fSDimitry Andric // Fill MBBs and Terminators, setting the addresses on the assumption
267f785676fSDimitry Andric // that no branches need relaxation.  Return the size of the function under
268f785676fSDimitry Andric // this assumption.
initMBBInfo()269f785676fSDimitry Andric uint64_t SystemZLongBranch::initMBBInfo() {
270f785676fSDimitry Andric   MF->RenumberBlocks();
271f785676fSDimitry Andric   unsigned NumBlocks = MF->size();
272f785676fSDimitry Andric 
273f785676fSDimitry Andric   MBBs.clear();
274f785676fSDimitry Andric   MBBs.resize(NumBlocks);
275f785676fSDimitry Andric 
276f785676fSDimitry Andric   Terminators.clear();
277f785676fSDimitry Andric   Terminators.reserve(NumBlocks);
278f785676fSDimitry Andric 
279f785676fSDimitry Andric   BlockPosition Position(MF->getAlignment());
280f785676fSDimitry Andric   for (unsigned I = 0; I < NumBlocks; ++I) {
281f785676fSDimitry Andric     MachineBasicBlock *MBB = MF->getBlockNumbered(I);
282f785676fSDimitry Andric     MBBInfo &Block = MBBs[I];
283f785676fSDimitry Andric 
284f785676fSDimitry Andric     // Record the alignment, for quick access.
285f785676fSDimitry Andric     Block.Alignment = MBB->getAlignment();
286f785676fSDimitry Andric 
287f785676fSDimitry Andric     // Calculate the size of the fixed part of the block.
288f785676fSDimitry Andric     MachineBasicBlock::iterator MI = MBB->begin();
289f785676fSDimitry Andric     MachineBasicBlock::iterator End = MBB->end();
290f785676fSDimitry Andric     while (MI != End && !MI->isTerminator()) {
2913ca95b02SDimitry Andric       Block.Size += TII->getInstSizeInBytes(*MI);
292f785676fSDimitry Andric       ++MI;
293f785676fSDimitry Andric     }
294f785676fSDimitry Andric     skipNonTerminators(Position, Block);
295f785676fSDimitry Andric 
296f785676fSDimitry Andric     // Add the terminators.
297f785676fSDimitry Andric     while (MI != End) {
298*4ba319b5SDimitry Andric       if (!MI->isDebugInstr()) {
299f785676fSDimitry Andric         assert(MI->isTerminator() && "Terminator followed by non-terminator");
3003ca95b02SDimitry Andric         Terminators.push_back(describeTerminator(*MI));
301f785676fSDimitry Andric         skipTerminator(Position, Terminators.back(), false);
302f785676fSDimitry Andric         ++Block.NumTerminators;
303f785676fSDimitry Andric       }
304f785676fSDimitry Andric       ++MI;
305f785676fSDimitry Andric     }
306f785676fSDimitry Andric   }
307f785676fSDimitry Andric 
308f785676fSDimitry Andric   return Position.Address;
309f785676fSDimitry Andric }
310f785676fSDimitry Andric 
311f785676fSDimitry Andric // Return true if, under current assumptions, Terminator would need to be
312f785676fSDimitry Andric // relaxed if it were placed at address Address.
mustRelaxBranch(const TerminatorInfo & Terminator,uint64_t Address)313f785676fSDimitry Andric bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator,
314f785676fSDimitry Andric                                         uint64_t Address) {
315*4ba319b5SDimitry Andric   if (!Terminator.Branch || Terminator.ExtraRelaxSize == 0)
316f785676fSDimitry Andric     return false;
317f785676fSDimitry Andric 
318f785676fSDimitry Andric   const MBBInfo &Target = MBBs[Terminator.TargetBlock];
319f785676fSDimitry Andric   if (Address >= Target.Address) {
320f785676fSDimitry Andric     if (Address - Target.Address <= MaxBackwardRange)
321f785676fSDimitry Andric       return false;
322f785676fSDimitry Andric   } else {
323f785676fSDimitry Andric     if (Target.Address - Address <= MaxForwardRange)
324f785676fSDimitry Andric       return false;
325f785676fSDimitry Andric   }
326f785676fSDimitry Andric 
327f785676fSDimitry Andric   return true;
328f785676fSDimitry Andric }
329f785676fSDimitry Andric 
330f785676fSDimitry Andric // Return true if, under current assumptions, any terminator needs
331f785676fSDimitry Andric // to be relaxed.
mustRelaxABranch()332f785676fSDimitry Andric bool SystemZLongBranch::mustRelaxABranch() {
33391bc56edSDimitry Andric   for (auto &Terminator : Terminators)
33491bc56edSDimitry Andric     if (mustRelaxBranch(Terminator, Terminator.Address))
335f785676fSDimitry Andric       return true;
336f785676fSDimitry Andric   return false;
337f785676fSDimitry Andric }
338f785676fSDimitry Andric 
339f785676fSDimitry Andric // Set the address of each block on the assumption that all branches
340f785676fSDimitry Andric // must be long.
setWorstCaseAddresses()341f785676fSDimitry Andric void SystemZLongBranch::setWorstCaseAddresses() {
342f785676fSDimitry Andric   SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
343f785676fSDimitry Andric   BlockPosition Position(MF->getAlignment());
34491bc56edSDimitry Andric   for (auto &Block : MBBs) {
34591bc56edSDimitry Andric     skipNonTerminators(Position, Block);
34691bc56edSDimitry Andric     for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) {
347f785676fSDimitry Andric       skipTerminator(Position, *TI, true);
348f785676fSDimitry Andric       ++TI;
349f785676fSDimitry Andric     }
350f785676fSDimitry Andric   }
351f785676fSDimitry Andric }
352f785676fSDimitry Andric 
353f785676fSDimitry Andric // Split BRANCH ON COUNT MI into the addition given by AddOpcode followed
354f785676fSDimitry Andric // by a BRCL on the result.
splitBranchOnCount(MachineInstr * MI,unsigned AddOpcode)355f785676fSDimitry Andric void SystemZLongBranch::splitBranchOnCount(MachineInstr *MI,
356f785676fSDimitry Andric                                            unsigned AddOpcode) {
357f785676fSDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
358f785676fSDimitry Andric   DebugLoc DL = MI->getDebugLoc();
359f785676fSDimitry Andric   BuildMI(*MBB, MI, DL, TII->get(AddOpcode))
3607a7e6055SDimitry Andric       .add(MI->getOperand(0))
3617a7e6055SDimitry Andric       .add(MI->getOperand(1))
362f785676fSDimitry Andric       .addImm(-1);
363f785676fSDimitry Andric   MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL))
364f785676fSDimitry Andric                            .addImm(SystemZ::CCMASK_ICMP)
365f785676fSDimitry Andric                            .addImm(SystemZ::CCMASK_CMP_NE)
3667a7e6055SDimitry Andric                            .add(MI->getOperand(2));
367f785676fSDimitry Andric   // The implicit use of CC is a killing use.
368f785676fSDimitry Andric   BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo());
369f785676fSDimitry Andric   MI->eraseFromParent();
370f785676fSDimitry Andric }
371f785676fSDimitry Andric 
372f785676fSDimitry Andric // Split MI into the comparison given by CompareOpcode followed
373f785676fSDimitry Andric // a BRCL on the result.
splitCompareBranch(MachineInstr * MI,unsigned CompareOpcode)374f785676fSDimitry Andric void SystemZLongBranch::splitCompareBranch(MachineInstr *MI,
375f785676fSDimitry Andric                                            unsigned CompareOpcode) {
376f785676fSDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
377f785676fSDimitry Andric   DebugLoc DL = MI->getDebugLoc();
378f785676fSDimitry Andric   BuildMI(*MBB, MI, DL, TII->get(CompareOpcode))
3797a7e6055SDimitry Andric       .add(MI->getOperand(0))
3807a7e6055SDimitry Andric       .add(MI->getOperand(1));
381f785676fSDimitry Andric   MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL))
382f785676fSDimitry Andric                            .addImm(SystemZ::CCMASK_ICMP)
3837a7e6055SDimitry Andric                            .add(MI->getOperand(2))
3847a7e6055SDimitry Andric                            .add(MI->getOperand(3));
385f785676fSDimitry Andric   // The implicit use of CC is a killing use.
386f785676fSDimitry Andric   BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo());
387f785676fSDimitry Andric   MI->eraseFromParent();
388f785676fSDimitry Andric }
389f785676fSDimitry Andric 
390f785676fSDimitry Andric // Relax the branch described by Terminator.
relaxBranch(TerminatorInfo & Terminator)391f785676fSDimitry Andric void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
392f785676fSDimitry Andric   MachineInstr *Branch = Terminator.Branch;
393f785676fSDimitry Andric   switch (Branch->getOpcode()) {
394f785676fSDimitry Andric   case SystemZ::J:
395f785676fSDimitry Andric     Branch->setDesc(TII->get(SystemZ::JG));
396f785676fSDimitry Andric     break;
397f785676fSDimitry Andric   case SystemZ::BRC:
398f785676fSDimitry Andric     Branch->setDesc(TII->get(SystemZ::BRCL));
399f785676fSDimitry Andric     break;
400f785676fSDimitry Andric   case SystemZ::BRCT:
401f785676fSDimitry Andric     splitBranchOnCount(Branch, SystemZ::AHI);
402f785676fSDimitry Andric     break;
403f785676fSDimitry Andric   case SystemZ::BRCTG:
404f785676fSDimitry Andric     splitBranchOnCount(Branch, SystemZ::AGHI);
405f785676fSDimitry Andric     break;
406f785676fSDimitry Andric   case SystemZ::CRJ:
407f785676fSDimitry Andric     splitCompareBranch(Branch, SystemZ::CR);
408f785676fSDimitry Andric     break;
409f785676fSDimitry Andric   case SystemZ::CGRJ:
410f785676fSDimitry Andric     splitCompareBranch(Branch, SystemZ::CGR);
411f785676fSDimitry Andric     break;
412f785676fSDimitry Andric   case SystemZ::CIJ:
413f785676fSDimitry Andric     splitCompareBranch(Branch, SystemZ::CHI);
414f785676fSDimitry Andric     break;
415f785676fSDimitry Andric   case SystemZ::CGIJ:
416f785676fSDimitry Andric     splitCompareBranch(Branch, SystemZ::CGHI);
417f785676fSDimitry Andric     break;
418f785676fSDimitry Andric   case SystemZ::CLRJ:
419f785676fSDimitry Andric     splitCompareBranch(Branch, SystemZ::CLR);
420f785676fSDimitry Andric     break;
421f785676fSDimitry Andric   case SystemZ::CLGRJ:
422f785676fSDimitry Andric     splitCompareBranch(Branch, SystemZ::CLGR);
423f785676fSDimitry Andric     break;
424f785676fSDimitry Andric   case SystemZ::CLIJ:
425f785676fSDimitry Andric     splitCompareBranch(Branch, SystemZ::CLFI);
426f785676fSDimitry Andric     break;
427f785676fSDimitry Andric   case SystemZ::CLGIJ:
428f785676fSDimitry Andric     splitCompareBranch(Branch, SystemZ::CLGFI);
429f785676fSDimitry Andric     break;
430f785676fSDimitry Andric   default:
431f785676fSDimitry Andric     llvm_unreachable("Unrecognized branch");
432f785676fSDimitry Andric   }
433f785676fSDimitry Andric 
434f785676fSDimitry Andric   Terminator.Size += Terminator.ExtraRelaxSize;
435f785676fSDimitry Andric   Terminator.ExtraRelaxSize = 0;
43691bc56edSDimitry Andric   Terminator.Branch = nullptr;
437f785676fSDimitry Andric 
438f785676fSDimitry Andric   ++LongBranches;
439f785676fSDimitry Andric }
440f785676fSDimitry Andric 
441f785676fSDimitry Andric // Run a shortening pass and relax any branches that need to be relaxed.
relaxBranches()442f785676fSDimitry Andric void SystemZLongBranch::relaxBranches() {
443f785676fSDimitry Andric   SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
444f785676fSDimitry Andric   BlockPosition Position(MF->getAlignment());
44591bc56edSDimitry Andric   for (auto &Block : MBBs) {
44691bc56edSDimitry Andric     skipNonTerminators(Position, Block);
44791bc56edSDimitry Andric     for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) {
448f785676fSDimitry Andric       assert(Position.Address <= TI->Address &&
449f785676fSDimitry Andric              "Addresses shouldn't go forwards");
450f785676fSDimitry Andric       if (mustRelaxBranch(*TI, Position.Address))
451f785676fSDimitry Andric         relaxBranch(*TI);
452f785676fSDimitry Andric       skipTerminator(Position, *TI, false);
453f785676fSDimitry Andric       ++TI;
454f785676fSDimitry Andric     }
455f785676fSDimitry Andric   }
456f785676fSDimitry Andric }
457f785676fSDimitry Andric 
runOnMachineFunction(MachineFunction & F)458f785676fSDimitry Andric bool SystemZLongBranch::runOnMachineFunction(MachineFunction &F) {
45939d628a0SDimitry Andric   TII = static_cast<const SystemZInstrInfo *>(F.getSubtarget().getInstrInfo());
460f785676fSDimitry Andric   MF = &F;
461f785676fSDimitry Andric   uint64_t Size = initMBBInfo();
462f785676fSDimitry Andric   if (Size <= MaxForwardRange || !mustRelaxABranch())
463f785676fSDimitry Andric     return false;
464f785676fSDimitry Andric 
465f785676fSDimitry Andric   setWorstCaseAddresses();
466f785676fSDimitry Andric   relaxBranches();
467f785676fSDimitry Andric   return true;
468f785676fSDimitry Andric }
4697a7e6055SDimitry Andric 
createSystemZLongBranchPass(SystemZTargetMachine & TM)4707a7e6055SDimitry Andric FunctionPass *llvm::createSystemZLongBranchPass(SystemZTargetMachine &TM) {
4717a7e6055SDimitry Andric   return new SystemZLongBranch(TM);
4727a7e6055SDimitry Andric }
473