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