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