10b57cec5SDimitry Andric //===-- SystemZLongBranch.cpp - Branch lengthening for SystemZ ------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This pass makes sure that all branches are in range. There are several ways 100b57cec5SDimitry Andric // in which this could be done. One aggressive approach is to assume that all 110b57cec5SDimitry Andric // branches are in range and successively replace those that turn out not 120b57cec5SDimitry Andric // to be in range with a longer form (branch relaxation). A simple 130b57cec5SDimitry Andric // implementation is to continually walk through the function relaxing 140b57cec5SDimitry Andric // branches until no more changes are needed and a fixed point is reached. 150b57cec5SDimitry Andric // However, in the pathological worst case, this implementation is 160b57cec5SDimitry Andric // quadratic in the number of blocks; relaxing branch N can make branch N-1 170b57cec5SDimitry Andric // go out of range, which in turn can make branch N-2 go out of range, 180b57cec5SDimitry Andric // and so on. 190b57cec5SDimitry Andric // 200b57cec5SDimitry Andric // An alternative approach is to assume that all branches must be 210b57cec5SDimitry Andric // converted to their long forms, then reinstate the short forms of 220b57cec5SDimitry Andric // branches that, even under this pessimistic assumption, turn out to be 230b57cec5SDimitry Andric // in range (branch shortening). This too can be implemented as a function 240b57cec5SDimitry Andric // walk that is repeated until a fixed point is reached. In general, 250b57cec5SDimitry Andric // the result of shortening is not as good as that of relaxation, and 260b57cec5SDimitry Andric // shortening is also quadratic in the worst case; shortening branch N 270b57cec5SDimitry Andric // can bring branch N-1 in range of the short form, which in turn can do 280b57cec5SDimitry Andric // the same for branch N-2, and so on. The main advantage of shortening 290b57cec5SDimitry Andric // is that each walk through the function produces valid code, so it is 300b57cec5SDimitry Andric // possible to stop at any point after the first walk. The quadraticness 310b57cec5SDimitry Andric // could therefore be handled with a maximum pass count, although the 320b57cec5SDimitry Andric // question then becomes: what maximum count should be used? 330b57cec5SDimitry Andric // 340b57cec5SDimitry Andric // On SystemZ, long branches are only needed for functions bigger than 64k, 350b57cec5SDimitry Andric // which are relatively rare to begin with, and the long branch sequences 360b57cec5SDimitry Andric // are actually relatively cheap. It therefore doesn't seem worth spending 370b57cec5SDimitry Andric // much compilation time on the problem. Instead, the approach we take is: 380b57cec5SDimitry Andric // 390b57cec5SDimitry Andric // (1) Work out the address that each block would have if no branches 400b57cec5SDimitry Andric // need relaxing. Exit the pass early if all branches are in range 410b57cec5SDimitry Andric // according to this assumption. 420b57cec5SDimitry Andric // 430b57cec5SDimitry Andric // (2) Work out the address that each block would have if all branches 440b57cec5SDimitry Andric // need relaxing. 450b57cec5SDimitry Andric // 460b57cec5SDimitry Andric // (3) Walk through the block calculating the final address of each instruction 470b57cec5SDimitry Andric // and relaxing those that need to be relaxed. For backward branches, 480b57cec5SDimitry Andric // this check uses the final address of the target block, as calculated 490b57cec5SDimitry Andric // earlier in the walk. For forward branches, this check uses the 500b57cec5SDimitry Andric // address of the target block that was calculated in (2). Both checks 510b57cec5SDimitry Andric // give a conservatively-correct range. 520b57cec5SDimitry Andric // 530b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric #include "SystemZ.h" 560b57cec5SDimitry Andric #include "SystemZInstrInfo.h" 570b57cec5SDimitry Andric #include "SystemZTargetMachine.h" 580b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 590b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 600b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 610b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 620b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 630b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 640b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 650b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 660b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h" 670b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 680b57cec5SDimitry Andric #include <cassert> 690b57cec5SDimitry Andric #include <cstdint> 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric using namespace llvm; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric #define DEBUG_TYPE "systemz-long-branch" 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric STATISTIC(LongBranches, "Number of long branches."); 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric namespace { 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric // Represents positional information about a basic block. 800b57cec5SDimitry Andric struct MBBInfo { 810b57cec5SDimitry Andric // The address that we currently assume the block has. 820b57cec5SDimitry Andric uint64_t Address = 0; 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric // The size of the block in bytes, excluding terminators. 850b57cec5SDimitry Andric // This value never changes. 860b57cec5SDimitry Andric uint64_t Size = 0; 870b57cec5SDimitry Andric 888bcb0991SDimitry Andric // The minimum alignment of the block. 890b57cec5SDimitry Andric // This value never changes. 908bcb0991SDimitry Andric Align Alignment; 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric // The number of terminators in this block. This value never changes. 930b57cec5SDimitry Andric unsigned NumTerminators = 0; 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric MBBInfo() = default; 960b57cec5SDimitry Andric }; 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric // Represents the state of a block terminator. 990b57cec5SDimitry Andric struct TerminatorInfo { 1000b57cec5SDimitry Andric // If this terminator is a relaxable branch, this points to the branch 1010b57cec5SDimitry Andric // instruction, otherwise it is null. 1020b57cec5SDimitry Andric MachineInstr *Branch = nullptr; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric // The address that we currently assume the terminator has. 1050b57cec5SDimitry Andric uint64_t Address = 0; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric // The current size of the terminator in bytes. 1080b57cec5SDimitry Andric uint64_t Size = 0; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric // If Branch is nonnull, this is the number of the target block, 1110b57cec5SDimitry Andric // otherwise it is unused. 1120b57cec5SDimitry Andric unsigned TargetBlock = 0; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric // If Branch is nonnull, this is the length of the longest relaxed form, 1150b57cec5SDimitry Andric // otherwise it is zero. 1160b57cec5SDimitry Andric unsigned ExtraRelaxSize = 0; 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric TerminatorInfo() = default; 1190b57cec5SDimitry Andric }; 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric // Used to keep track of the current position while iterating over the blocks. 1220b57cec5SDimitry Andric struct BlockPosition { 1230b57cec5SDimitry Andric // The address that we assume this position has. 1240b57cec5SDimitry Andric uint64_t Address = 0; 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric // The number of low bits in Address that are known to be the same 1270b57cec5SDimitry Andric // as the runtime address. 1280b57cec5SDimitry Andric unsigned KnownBits; 1290b57cec5SDimitry Andric 1308bcb0991SDimitry Andric BlockPosition(unsigned InitialLogAlignment) 1318bcb0991SDimitry Andric : KnownBits(InitialLogAlignment) {} 1320b57cec5SDimitry Andric }; 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric class SystemZLongBranch : public MachineFunctionPass { 1350b57cec5SDimitry Andric public: 1360b57cec5SDimitry Andric static char ID; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric SystemZLongBranch(const SystemZTargetMachine &tm) 1390b57cec5SDimitry Andric : MachineFunctionPass(ID) {} 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric StringRef getPassName() const override { return "SystemZ Long Branch"; } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &F) override; 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 1460b57cec5SDimitry Andric return MachineFunctionProperties().set( 1470b57cec5SDimitry Andric MachineFunctionProperties::Property::NoVRegs); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric private: 1510b57cec5SDimitry Andric void skipNonTerminators(BlockPosition &Position, MBBInfo &Block); 1520b57cec5SDimitry Andric void skipTerminator(BlockPosition &Position, TerminatorInfo &Terminator, 1530b57cec5SDimitry Andric bool AssumeRelaxed); 1540b57cec5SDimitry Andric TerminatorInfo describeTerminator(MachineInstr &MI); 1550b57cec5SDimitry Andric uint64_t initMBBInfo(); 1560b57cec5SDimitry Andric bool mustRelaxBranch(const TerminatorInfo &Terminator, uint64_t Address); 1570b57cec5SDimitry Andric bool mustRelaxABranch(); 1580b57cec5SDimitry Andric void setWorstCaseAddresses(); 1590b57cec5SDimitry Andric void splitBranchOnCount(MachineInstr *MI, unsigned AddOpcode); 1600b57cec5SDimitry Andric void splitCompareBranch(MachineInstr *MI, unsigned CompareOpcode); 1610b57cec5SDimitry Andric void relaxBranch(TerminatorInfo &Terminator); 1620b57cec5SDimitry Andric void relaxBranches(); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric const SystemZInstrInfo *TII = nullptr; 165480093f4SDimitry Andric MachineFunction *MF = nullptr; 1660b57cec5SDimitry Andric SmallVector<MBBInfo, 16> MBBs; 1670b57cec5SDimitry Andric SmallVector<TerminatorInfo, 16> Terminators; 1680b57cec5SDimitry Andric }; 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric char SystemZLongBranch::ID = 0; 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric const uint64_t MaxBackwardRange = 0x10000; 1730b57cec5SDimitry Andric const uint64_t MaxForwardRange = 0xfffe; 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric } // end anonymous namespace 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric // Position describes the state immediately before Block. Update Block 1780b57cec5SDimitry Andric // accordingly and move Position to the end of the block's non-terminator 1790b57cec5SDimitry Andric // instructions. 1800b57cec5SDimitry Andric void SystemZLongBranch::skipNonTerminators(BlockPosition &Position, 1810b57cec5SDimitry Andric MBBInfo &Block) { 1828bcb0991SDimitry Andric if (Log2(Block.Alignment) > Position.KnownBits) { 1830b57cec5SDimitry Andric // When calculating the address of Block, we need to conservatively 1840b57cec5SDimitry Andric // assume that Block had the worst possible misalignment. 1858bcb0991SDimitry Andric Position.Address += 1868bcb0991SDimitry Andric (Block.Alignment.value() - (uint64_t(1) << Position.KnownBits)); 1878bcb0991SDimitry Andric Position.KnownBits = Log2(Block.Alignment); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric // Align the addresses. 1918bcb0991SDimitry Andric Position.Address = alignTo(Position.Address, Block.Alignment); 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric // Record the block's position. 1940b57cec5SDimitry Andric Block.Address = Position.Address; 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric // Move past the non-terminators in the block. 1970b57cec5SDimitry Andric Position.Address += Block.Size; 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric // Position describes the state immediately before Terminator. 2010b57cec5SDimitry Andric // Update Terminator accordingly and move Position past it. 2020b57cec5SDimitry Andric // Assume that Terminator will be relaxed if AssumeRelaxed. 2030b57cec5SDimitry Andric void SystemZLongBranch::skipTerminator(BlockPosition &Position, 2040b57cec5SDimitry Andric TerminatorInfo &Terminator, 2050b57cec5SDimitry Andric bool AssumeRelaxed) { 2060b57cec5SDimitry Andric Terminator.Address = Position.Address; 2070b57cec5SDimitry Andric Position.Address += Terminator.Size; 2080b57cec5SDimitry Andric if (AssumeRelaxed) 2090b57cec5SDimitry Andric Position.Address += Terminator.ExtraRelaxSize; 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 212*349cc55cSDimitry Andric static unsigned getInstSizeInBytes(const MachineInstr &MI, 213*349cc55cSDimitry Andric const SystemZInstrInfo *TII) { 214*349cc55cSDimitry Andric unsigned Size = TII->getInstSizeInBytes(MI); 215*349cc55cSDimitry Andric assert((Size || 216*349cc55cSDimitry Andric // These do not have a size: 217*349cc55cSDimitry Andric MI.isDebugOrPseudoInstr() || MI.isPosition() || MI.isKill() || 218*349cc55cSDimitry Andric MI.isImplicitDef() || MI.getOpcode() == SystemZ::MemBarrier || 219*349cc55cSDimitry Andric // These have a size that may be zero: 220*349cc55cSDimitry Andric MI.isInlineAsm() || MI.getOpcode() == SystemZ::STACKMAP || 221*349cc55cSDimitry Andric MI.getOpcode() == SystemZ::PATCHPOINT) && 222*349cc55cSDimitry Andric "Missing size value for instruction."); 223*349cc55cSDimitry Andric return Size; 224*349cc55cSDimitry Andric } 225*349cc55cSDimitry Andric 2260b57cec5SDimitry Andric // Return a description of terminator instruction MI. 2270b57cec5SDimitry Andric TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr &MI) { 2280b57cec5SDimitry Andric TerminatorInfo Terminator; 229*349cc55cSDimitry Andric Terminator.Size = getInstSizeInBytes(MI, TII); 2300b57cec5SDimitry Andric if (MI.isConditionalBranch() || MI.isUnconditionalBranch()) { 2310b57cec5SDimitry Andric switch (MI.getOpcode()) { 2320b57cec5SDimitry Andric case SystemZ::J: 2330b57cec5SDimitry Andric // Relaxes to JG, which is 2 bytes longer. 2340b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 2; 2350b57cec5SDimitry Andric break; 2360b57cec5SDimitry Andric case SystemZ::BRC: 2370b57cec5SDimitry Andric // Relaxes to BRCL, which is 2 bytes longer. 2380b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 2; 2390b57cec5SDimitry Andric break; 2400b57cec5SDimitry Andric case SystemZ::BRCT: 2410b57cec5SDimitry Andric case SystemZ::BRCTG: 2420b57cec5SDimitry Andric // Relaxes to A(G)HI and BRCL, which is 6 bytes longer. 2430b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 6; 2440b57cec5SDimitry Andric break; 2450b57cec5SDimitry Andric case SystemZ::BRCTH: 2460b57cec5SDimitry Andric // Never needs to be relaxed. 2470b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 0; 2480b57cec5SDimitry Andric break; 2490b57cec5SDimitry Andric case SystemZ::CRJ: 2500b57cec5SDimitry Andric case SystemZ::CLRJ: 2510b57cec5SDimitry Andric // Relaxes to a C(L)R/BRCL sequence, which is 2 bytes longer. 2520b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 2; 2530b57cec5SDimitry Andric break; 2540b57cec5SDimitry Andric case SystemZ::CGRJ: 2550b57cec5SDimitry Andric case SystemZ::CLGRJ: 2560b57cec5SDimitry Andric // Relaxes to a C(L)GR/BRCL sequence, which is 4 bytes longer. 2570b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 4; 2580b57cec5SDimitry Andric break; 2590b57cec5SDimitry Andric case SystemZ::CIJ: 2600b57cec5SDimitry Andric case SystemZ::CGIJ: 2610b57cec5SDimitry Andric // Relaxes to a C(G)HI/BRCL sequence, which is 4 bytes longer. 2620b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 4; 2630b57cec5SDimitry Andric break; 2640b57cec5SDimitry Andric case SystemZ::CLIJ: 2650b57cec5SDimitry Andric case SystemZ::CLGIJ: 2660b57cec5SDimitry Andric // Relaxes to a CL(G)FI/BRCL sequence, which is 6 bytes longer. 2670b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 6; 2680b57cec5SDimitry Andric break; 2690b57cec5SDimitry Andric default: 2700b57cec5SDimitry Andric llvm_unreachable("Unrecognized branch instruction"); 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric Terminator.Branch = &MI; 2730b57cec5SDimitry Andric Terminator.TargetBlock = 2740b57cec5SDimitry Andric TII->getBranchInfo(MI).getMBBTarget()->getNumber(); 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric return Terminator; 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric // Fill MBBs and Terminators, setting the addresses on the assumption 2800b57cec5SDimitry Andric // that no branches need relaxation. Return the size of the function under 2810b57cec5SDimitry Andric // this assumption. 2820b57cec5SDimitry Andric uint64_t SystemZLongBranch::initMBBInfo() { 2830b57cec5SDimitry Andric MF->RenumberBlocks(); 2840b57cec5SDimitry Andric unsigned NumBlocks = MF->size(); 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric MBBs.clear(); 2870b57cec5SDimitry Andric MBBs.resize(NumBlocks); 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric Terminators.clear(); 2900b57cec5SDimitry Andric Terminators.reserve(NumBlocks); 2910b57cec5SDimitry Andric 2928bcb0991SDimitry Andric BlockPosition Position(Log2(MF->getAlignment())); 2930b57cec5SDimitry Andric for (unsigned I = 0; I < NumBlocks; ++I) { 2940b57cec5SDimitry Andric MachineBasicBlock *MBB = MF->getBlockNumbered(I); 2950b57cec5SDimitry Andric MBBInfo &Block = MBBs[I]; 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric // Record the alignment, for quick access. 2980b57cec5SDimitry Andric Block.Alignment = MBB->getAlignment(); 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric // Calculate the size of the fixed part of the block. 3010b57cec5SDimitry Andric MachineBasicBlock::iterator MI = MBB->begin(); 3020b57cec5SDimitry Andric MachineBasicBlock::iterator End = MBB->end(); 3030b57cec5SDimitry Andric while (MI != End && !MI->isTerminator()) { 304*349cc55cSDimitry Andric Block.Size += getInstSizeInBytes(*MI, TII); 3050b57cec5SDimitry Andric ++MI; 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric skipNonTerminators(Position, Block); 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric // Add the terminators. 3100b57cec5SDimitry Andric while (MI != End) { 3110b57cec5SDimitry Andric if (!MI->isDebugInstr()) { 3120b57cec5SDimitry Andric assert(MI->isTerminator() && "Terminator followed by non-terminator"); 3130b57cec5SDimitry Andric Terminators.push_back(describeTerminator(*MI)); 3140b57cec5SDimitry Andric skipTerminator(Position, Terminators.back(), false); 3150b57cec5SDimitry Andric ++Block.NumTerminators; 3160b57cec5SDimitry Andric } 3170b57cec5SDimitry Andric ++MI; 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric return Position.Address; 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric // Return true if, under current assumptions, Terminator would need to be 3250b57cec5SDimitry Andric // relaxed if it were placed at address Address. 3260b57cec5SDimitry Andric bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator, 3270b57cec5SDimitry Andric uint64_t Address) { 3280b57cec5SDimitry Andric if (!Terminator.Branch || Terminator.ExtraRelaxSize == 0) 3290b57cec5SDimitry Andric return false; 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric const MBBInfo &Target = MBBs[Terminator.TargetBlock]; 3320b57cec5SDimitry Andric if (Address >= Target.Address) { 3330b57cec5SDimitry Andric if (Address - Target.Address <= MaxBackwardRange) 3340b57cec5SDimitry Andric return false; 3350b57cec5SDimitry Andric } else { 3360b57cec5SDimitry Andric if (Target.Address - Address <= MaxForwardRange) 3370b57cec5SDimitry Andric return false; 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric return true; 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric // Return true if, under current assumptions, any terminator needs 3440b57cec5SDimitry Andric // to be relaxed. 3450b57cec5SDimitry Andric bool SystemZLongBranch::mustRelaxABranch() { 3460b57cec5SDimitry Andric for (auto &Terminator : Terminators) 3470b57cec5SDimitry Andric if (mustRelaxBranch(Terminator, Terminator.Address)) 3480b57cec5SDimitry Andric return true; 3490b57cec5SDimitry Andric return false; 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric // Set the address of each block on the assumption that all branches 3530b57cec5SDimitry Andric // must be long. 3540b57cec5SDimitry Andric void SystemZLongBranch::setWorstCaseAddresses() { 3550b57cec5SDimitry Andric SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin(); 3568bcb0991SDimitry Andric BlockPosition Position(Log2(MF->getAlignment())); 3570b57cec5SDimitry Andric for (auto &Block : MBBs) { 3580b57cec5SDimitry Andric skipNonTerminators(Position, Block); 3590b57cec5SDimitry Andric for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) { 3600b57cec5SDimitry Andric skipTerminator(Position, *TI, true); 3610b57cec5SDimitry Andric ++TI; 3620b57cec5SDimitry Andric } 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric // Split BRANCH ON COUNT MI into the addition given by AddOpcode followed 3670b57cec5SDimitry Andric // by a BRCL on the result. 3680b57cec5SDimitry Andric void SystemZLongBranch::splitBranchOnCount(MachineInstr *MI, 3690b57cec5SDimitry Andric unsigned AddOpcode) { 3700b57cec5SDimitry Andric MachineBasicBlock *MBB = MI->getParent(); 3710b57cec5SDimitry Andric DebugLoc DL = MI->getDebugLoc(); 3720b57cec5SDimitry Andric BuildMI(*MBB, MI, DL, TII->get(AddOpcode)) 3730b57cec5SDimitry Andric .add(MI->getOperand(0)) 3740b57cec5SDimitry Andric .add(MI->getOperand(1)) 3750b57cec5SDimitry Andric .addImm(-1); 3760b57cec5SDimitry Andric MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL)) 3770b57cec5SDimitry Andric .addImm(SystemZ::CCMASK_ICMP) 3780b57cec5SDimitry Andric .addImm(SystemZ::CCMASK_CMP_NE) 3790b57cec5SDimitry Andric .add(MI->getOperand(2)); 3800b57cec5SDimitry Andric // The implicit use of CC is a killing use. 3810b57cec5SDimitry Andric BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo()); 3820b57cec5SDimitry Andric MI->eraseFromParent(); 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric // Split MI into the comparison given by CompareOpcode followed 3860b57cec5SDimitry Andric // a BRCL on the result. 3870b57cec5SDimitry Andric void SystemZLongBranch::splitCompareBranch(MachineInstr *MI, 3880b57cec5SDimitry Andric unsigned CompareOpcode) { 3890b57cec5SDimitry Andric MachineBasicBlock *MBB = MI->getParent(); 3900b57cec5SDimitry Andric DebugLoc DL = MI->getDebugLoc(); 3910b57cec5SDimitry Andric BuildMI(*MBB, MI, DL, TII->get(CompareOpcode)) 3920b57cec5SDimitry Andric .add(MI->getOperand(0)) 3930b57cec5SDimitry Andric .add(MI->getOperand(1)); 3940b57cec5SDimitry Andric MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL)) 3950b57cec5SDimitry Andric .addImm(SystemZ::CCMASK_ICMP) 3960b57cec5SDimitry Andric .add(MI->getOperand(2)) 3970b57cec5SDimitry Andric .add(MI->getOperand(3)); 3980b57cec5SDimitry Andric // The implicit use of CC is a killing use. 3990b57cec5SDimitry Andric BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo()); 4000b57cec5SDimitry Andric MI->eraseFromParent(); 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric // Relax the branch described by Terminator. 4040b57cec5SDimitry Andric void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) { 4050b57cec5SDimitry Andric MachineInstr *Branch = Terminator.Branch; 4060b57cec5SDimitry Andric switch (Branch->getOpcode()) { 4070b57cec5SDimitry Andric case SystemZ::J: 4080b57cec5SDimitry Andric Branch->setDesc(TII->get(SystemZ::JG)); 4090b57cec5SDimitry Andric break; 4100b57cec5SDimitry Andric case SystemZ::BRC: 4110b57cec5SDimitry Andric Branch->setDesc(TII->get(SystemZ::BRCL)); 4120b57cec5SDimitry Andric break; 4130b57cec5SDimitry Andric case SystemZ::BRCT: 4140b57cec5SDimitry Andric splitBranchOnCount(Branch, SystemZ::AHI); 4150b57cec5SDimitry Andric break; 4160b57cec5SDimitry Andric case SystemZ::BRCTG: 4170b57cec5SDimitry Andric splitBranchOnCount(Branch, SystemZ::AGHI); 4180b57cec5SDimitry Andric break; 4190b57cec5SDimitry Andric case SystemZ::CRJ: 4200b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CR); 4210b57cec5SDimitry Andric break; 4220b57cec5SDimitry Andric case SystemZ::CGRJ: 4230b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CGR); 4240b57cec5SDimitry Andric break; 4250b57cec5SDimitry Andric case SystemZ::CIJ: 4260b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CHI); 4270b57cec5SDimitry Andric break; 4280b57cec5SDimitry Andric case SystemZ::CGIJ: 4290b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CGHI); 4300b57cec5SDimitry Andric break; 4310b57cec5SDimitry Andric case SystemZ::CLRJ: 4320b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CLR); 4330b57cec5SDimitry Andric break; 4340b57cec5SDimitry Andric case SystemZ::CLGRJ: 4350b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CLGR); 4360b57cec5SDimitry Andric break; 4370b57cec5SDimitry Andric case SystemZ::CLIJ: 4380b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CLFI); 4390b57cec5SDimitry Andric break; 4400b57cec5SDimitry Andric case SystemZ::CLGIJ: 4410b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CLGFI); 4420b57cec5SDimitry Andric break; 4430b57cec5SDimitry Andric default: 4440b57cec5SDimitry Andric llvm_unreachable("Unrecognized branch"); 4450b57cec5SDimitry Andric } 4460b57cec5SDimitry Andric 4470b57cec5SDimitry Andric Terminator.Size += Terminator.ExtraRelaxSize; 4480b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 0; 4490b57cec5SDimitry Andric Terminator.Branch = nullptr; 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric ++LongBranches; 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric // Run a shortening pass and relax any branches that need to be relaxed. 4550b57cec5SDimitry Andric void SystemZLongBranch::relaxBranches() { 4560b57cec5SDimitry Andric SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin(); 4578bcb0991SDimitry Andric BlockPosition Position(Log2(MF->getAlignment())); 4580b57cec5SDimitry Andric for (auto &Block : MBBs) { 4590b57cec5SDimitry Andric skipNonTerminators(Position, Block); 4600b57cec5SDimitry Andric for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) { 4610b57cec5SDimitry Andric assert(Position.Address <= TI->Address && 4620b57cec5SDimitry Andric "Addresses shouldn't go forwards"); 4630b57cec5SDimitry Andric if (mustRelaxBranch(*TI, Position.Address)) 4640b57cec5SDimitry Andric relaxBranch(*TI); 4650b57cec5SDimitry Andric skipTerminator(Position, *TI, false); 4660b57cec5SDimitry Andric ++TI; 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric } 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric bool SystemZLongBranch::runOnMachineFunction(MachineFunction &F) { 4720b57cec5SDimitry Andric TII = static_cast<const SystemZInstrInfo *>(F.getSubtarget().getInstrInfo()); 4730b57cec5SDimitry Andric MF = &F; 4740b57cec5SDimitry Andric uint64_t Size = initMBBInfo(); 4750b57cec5SDimitry Andric if (Size <= MaxForwardRange || !mustRelaxABranch()) 4760b57cec5SDimitry Andric return false; 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric setWorstCaseAddresses(); 4790b57cec5SDimitry Andric relaxBranches(); 4800b57cec5SDimitry Andric return true; 4810b57cec5SDimitry Andric } 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric FunctionPass *llvm::createSystemZLongBranchPass(SystemZTargetMachine &TM) { 4840b57cec5SDimitry Andric return new SystemZLongBranch(TM); 4850b57cec5SDimitry Andric } 486