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