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 138*04eeddc0SDimitry Andric SystemZLongBranch() : MachineFunctionPass(ID) { 139*04eeddc0SDimitry Andric initializeSystemZLongBranchPass(*PassRegistry::getPassRegistry()); 140*04eeddc0SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &F) override; 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 1450b57cec5SDimitry Andric return MachineFunctionProperties().set( 1460b57cec5SDimitry Andric MachineFunctionProperties::Property::NoVRegs); 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric private: 1500b57cec5SDimitry Andric void skipNonTerminators(BlockPosition &Position, MBBInfo &Block); 1510b57cec5SDimitry Andric void skipTerminator(BlockPosition &Position, TerminatorInfo &Terminator, 1520b57cec5SDimitry Andric bool AssumeRelaxed); 1530b57cec5SDimitry Andric TerminatorInfo describeTerminator(MachineInstr &MI); 1540b57cec5SDimitry Andric uint64_t initMBBInfo(); 1550b57cec5SDimitry Andric bool mustRelaxBranch(const TerminatorInfo &Terminator, uint64_t Address); 1560b57cec5SDimitry Andric bool mustRelaxABranch(); 1570b57cec5SDimitry Andric void setWorstCaseAddresses(); 1580b57cec5SDimitry Andric void splitBranchOnCount(MachineInstr *MI, unsigned AddOpcode); 1590b57cec5SDimitry Andric void splitCompareBranch(MachineInstr *MI, unsigned CompareOpcode); 1600b57cec5SDimitry Andric void relaxBranch(TerminatorInfo &Terminator); 1610b57cec5SDimitry Andric void relaxBranches(); 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric const SystemZInstrInfo *TII = nullptr; 164480093f4SDimitry Andric MachineFunction *MF = nullptr; 1650b57cec5SDimitry Andric SmallVector<MBBInfo, 16> MBBs; 1660b57cec5SDimitry Andric SmallVector<TerminatorInfo, 16> Terminators; 1670b57cec5SDimitry Andric }; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric char SystemZLongBranch::ID = 0; 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric const uint64_t MaxBackwardRange = 0x10000; 1720b57cec5SDimitry Andric const uint64_t MaxForwardRange = 0xfffe; 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric } // end anonymous namespace 1750b57cec5SDimitry Andric 176*04eeddc0SDimitry Andric INITIALIZE_PASS(SystemZLongBranch, DEBUG_TYPE, "SystemZ Long Branch", false, 177*04eeddc0SDimitry Andric false) 178*04eeddc0SDimitry Andric 1790b57cec5SDimitry Andric // Position describes the state immediately before Block. Update Block 1800b57cec5SDimitry Andric // accordingly and move Position to the end of the block's non-terminator 1810b57cec5SDimitry Andric // instructions. 1820b57cec5SDimitry Andric void SystemZLongBranch::skipNonTerminators(BlockPosition &Position, 1830b57cec5SDimitry Andric MBBInfo &Block) { 1848bcb0991SDimitry Andric if (Log2(Block.Alignment) > Position.KnownBits) { 1850b57cec5SDimitry Andric // When calculating the address of Block, we need to conservatively 1860b57cec5SDimitry Andric // assume that Block had the worst possible misalignment. 1878bcb0991SDimitry Andric Position.Address += 1888bcb0991SDimitry Andric (Block.Alignment.value() - (uint64_t(1) << Position.KnownBits)); 1898bcb0991SDimitry Andric Position.KnownBits = Log2(Block.Alignment); 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric // Align the addresses. 1938bcb0991SDimitry Andric Position.Address = alignTo(Position.Address, Block.Alignment); 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric // Record the block's position. 1960b57cec5SDimitry Andric Block.Address = Position.Address; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric // Move past the non-terminators in the block. 1990b57cec5SDimitry Andric Position.Address += Block.Size; 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric // Position describes the state immediately before Terminator. 2030b57cec5SDimitry Andric // Update Terminator accordingly and move Position past it. 2040b57cec5SDimitry Andric // Assume that Terminator will be relaxed if AssumeRelaxed. 2050b57cec5SDimitry Andric void SystemZLongBranch::skipTerminator(BlockPosition &Position, 2060b57cec5SDimitry Andric TerminatorInfo &Terminator, 2070b57cec5SDimitry Andric bool AssumeRelaxed) { 2080b57cec5SDimitry Andric Terminator.Address = Position.Address; 2090b57cec5SDimitry Andric Position.Address += Terminator.Size; 2100b57cec5SDimitry Andric if (AssumeRelaxed) 2110b57cec5SDimitry Andric Position.Address += Terminator.ExtraRelaxSize; 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 214349cc55cSDimitry Andric static unsigned getInstSizeInBytes(const MachineInstr &MI, 215349cc55cSDimitry Andric const SystemZInstrInfo *TII) { 216349cc55cSDimitry Andric unsigned Size = TII->getInstSizeInBytes(MI); 217349cc55cSDimitry Andric assert((Size || 218349cc55cSDimitry Andric // These do not have a size: 219349cc55cSDimitry Andric MI.isDebugOrPseudoInstr() || MI.isPosition() || MI.isKill() || 220349cc55cSDimitry Andric MI.isImplicitDef() || MI.getOpcode() == SystemZ::MemBarrier || 221349cc55cSDimitry Andric // These have a size that may be zero: 222349cc55cSDimitry Andric MI.isInlineAsm() || MI.getOpcode() == SystemZ::STACKMAP || 223349cc55cSDimitry Andric MI.getOpcode() == SystemZ::PATCHPOINT) && 224349cc55cSDimitry Andric "Missing size value for instruction."); 225349cc55cSDimitry Andric return Size; 226349cc55cSDimitry Andric } 227349cc55cSDimitry Andric 2280b57cec5SDimitry Andric // Return a description of terminator instruction MI. 2290b57cec5SDimitry Andric TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr &MI) { 2300b57cec5SDimitry Andric TerminatorInfo Terminator; 231349cc55cSDimitry Andric Terminator.Size = getInstSizeInBytes(MI, TII); 2320b57cec5SDimitry Andric if (MI.isConditionalBranch() || MI.isUnconditionalBranch()) { 2330b57cec5SDimitry Andric switch (MI.getOpcode()) { 2340b57cec5SDimitry Andric case SystemZ::J: 2350b57cec5SDimitry Andric // Relaxes to JG, which is 2 bytes longer. 2360b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 2; 2370b57cec5SDimitry Andric break; 2380b57cec5SDimitry Andric case SystemZ::BRC: 2390b57cec5SDimitry Andric // Relaxes to BRCL, which is 2 bytes longer. 2400b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 2; 2410b57cec5SDimitry Andric break; 2420b57cec5SDimitry Andric case SystemZ::BRCT: 2430b57cec5SDimitry Andric case SystemZ::BRCTG: 2440b57cec5SDimitry Andric // Relaxes to A(G)HI and BRCL, which is 6 bytes longer. 2450b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 6; 2460b57cec5SDimitry Andric break; 2470b57cec5SDimitry Andric case SystemZ::BRCTH: 2480b57cec5SDimitry Andric // Never needs to be relaxed. 2490b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 0; 2500b57cec5SDimitry Andric break; 2510b57cec5SDimitry Andric case SystemZ::CRJ: 2520b57cec5SDimitry Andric case SystemZ::CLRJ: 2530b57cec5SDimitry Andric // Relaxes to a C(L)R/BRCL sequence, which is 2 bytes longer. 2540b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 2; 2550b57cec5SDimitry Andric break; 2560b57cec5SDimitry Andric case SystemZ::CGRJ: 2570b57cec5SDimitry Andric case SystemZ::CLGRJ: 2580b57cec5SDimitry Andric // Relaxes to a C(L)GR/BRCL sequence, which is 4 bytes longer. 2590b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 4; 2600b57cec5SDimitry Andric break; 2610b57cec5SDimitry Andric case SystemZ::CIJ: 2620b57cec5SDimitry Andric case SystemZ::CGIJ: 2630b57cec5SDimitry Andric // Relaxes to a C(G)HI/BRCL sequence, which is 4 bytes longer. 2640b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 4; 2650b57cec5SDimitry Andric break; 2660b57cec5SDimitry Andric case SystemZ::CLIJ: 2670b57cec5SDimitry Andric case SystemZ::CLGIJ: 2680b57cec5SDimitry Andric // Relaxes to a CL(G)FI/BRCL sequence, which is 6 bytes longer. 2690b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 6; 2700b57cec5SDimitry Andric break; 2710b57cec5SDimitry Andric default: 2720b57cec5SDimitry Andric llvm_unreachable("Unrecognized branch instruction"); 2730b57cec5SDimitry Andric } 2740b57cec5SDimitry Andric Terminator.Branch = &MI; 2750b57cec5SDimitry Andric Terminator.TargetBlock = 2760b57cec5SDimitry Andric TII->getBranchInfo(MI).getMBBTarget()->getNumber(); 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric return Terminator; 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric // Fill MBBs and Terminators, setting the addresses on the assumption 2820b57cec5SDimitry Andric // that no branches need relaxation. Return the size of the function under 2830b57cec5SDimitry Andric // this assumption. 2840b57cec5SDimitry Andric uint64_t SystemZLongBranch::initMBBInfo() { 2850b57cec5SDimitry Andric MF->RenumberBlocks(); 2860b57cec5SDimitry Andric unsigned NumBlocks = MF->size(); 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric MBBs.clear(); 2890b57cec5SDimitry Andric MBBs.resize(NumBlocks); 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric Terminators.clear(); 2920b57cec5SDimitry Andric Terminators.reserve(NumBlocks); 2930b57cec5SDimitry Andric 2948bcb0991SDimitry Andric BlockPosition Position(Log2(MF->getAlignment())); 2950b57cec5SDimitry Andric for (unsigned I = 0; I < NumBlocks; ++I) { 2960b57cec5SDimitry Andric MachineBasicBlock *MBB = MF->getBlockNumbered(I); 2970b57cec5SDimitry Andric MBBInfo &Block = MBBs[I]; 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric // Record the alignment, for quick access. 3000b57cec5SDimitry Andric Block.Alignment = MBB->getAlignment(); 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric // Calculate the size of the fixed part of the block. 3030b57cec5SDimitry Andric MachineBasicBlock::iterator MI = MBB->begin(); 3040b57cec5SDimitry Andric MachineBasicBlock::iterator End = MBB->end(); 3050b57cec5SDimitry Andric while (MI != End && !MI->isTerminator()) { 306349cc55cSDimitry Andric Block.Size += getInstSizeInBytes(*MI, TII); 3070b57cec5SDimitry Andric ++MI; 3080b57cec5SDimitry Andric } 3090b57cec5SDimitry Andric skipNonTerminators(Position, Block); 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric // Add the terminators. 3120b57cec5SDimitry Andric while (MI != End) { 3130b57cec5SDimitry Andric if (!MI->isDebugInstr()) { 3140b57cec5SDimitry Andric assert(MI->isTerminator() && "Terminator followed by non-terminator"); 3150b57cec5SDimitry Andric Terminators.push_back(describeTerminator(*MI)); 3160b57cec5SDimitry Andric skipTerminator(Position, Terminators.back(), false); 3170b57cec5SDimitry Andric ++Block.NumTerminators; 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric ++MI; 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric return Position.Address; 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric // Return true if, under current assumptions, Terminator would need to be 3270b57cec5SDimitry Andric // relaxed if it were placed at address Address. 3280b57cec5SDimitry Andric bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator, 3290b57cec5SDimitry Andric uint64_t Address) { 3300b57cec5SDimitry Andric if (!Terminator.Branch || Terminator.ExtraRelaxSize == 0) 3310b57cec5SDimitry Andric return false; 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric const MBBInfo &Target = MBBs[Terminator.TargetBlock]; 3340b57cec5SDimitry Andric if (Address >= Target.Address) { 3350b57cec5SDimitry Andric if (Address - Target.Address <= MaxBackwardRange) 3360b57cec5SDimitry Andric return false; 3370b57cec5SDimitry Andric } else { 3380b57cec5SDimitry Andric if (Target.Address - Address <= MaxForwardRange) 3390b57cec5SDimitry Andric return false; 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric return true; 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric // Return true if, under current assumptions, any terminator needs 3460b57cec5SDimitry Andric // to be relaxed. 3470b57cec5SDimitry Andric bool SystemZLongBranch::mustRelaxABranch() { 3480b57cec5SDimitry Andric for (auto &Terminator : Terminators) 3490b57cec5SDimitry Andric if (mustRelaxBranch(Terminator, Terminator.Address)) 3500b57cec5SDimitry Andric return true; 3510b57cec5SDimitry Andric return false; 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric // Set the address of each block on the assumption that all branches 3550b57cec5SDimitry Andric // must be long. 3560b57cec5SDimitry Andric void SystemZLongBranch::setWorstCaseAddresses() { 3570b57cec5SDimitry Andric SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin(); 3588bcb0991SDimitry Andric BlockPosition Position(Log2(MF->getAlignment())); 3590b57cec5SDimitry Andric for (auto &Block : MBBs) { 3600b57cec5SDimitry Andric skipNonTerminators(Position, Block); 3610b57cec5SDimitry Andric for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) { 3620b57cec5SDimitry Andric skipTerminator(Position, *TI, true); 3630b57cec5SDimitry Andric ++TI; 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric // Split BRANCH ON COUNT MI into the addition given by AddOpcode followed 3690b57cec5SDimitry Andric // by a BRCL on the result. 3700b57cec5SDimitry Andric void SystemZLongBranch::splitBranchOnCount(MachineInstr *MI, 3710b57cec5SDimitry Andric unsigned AddOpcode) { 3720b57cec5SDimitry Andric MachineBasicBlock *MBB = MI->getParent(); 3730b57cec5SDimitry Andric DebugLoc DL = MI->getDebugLoc(); 3740b57cec5SDimitry Andric BuildMI(*MBB, MI, DL, TII->get(AddOpcode)) 3750b57cec5SDimitry Andric .add(MI->getOperand(0)) 3760b57cec5SDimitry Andric .add(MI->getOperand(1)) 3770b57cec5SDimitry Andric .addImm(-1); 3780b57cec5SDimitry Andric MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL)) 3790b57cec5SDimitry Andric .addImm(SystemZ::CCMASK_ICMP) 3800b57cec5SDimitry Andric .addImm(SystemZ::CCMASK_CMP_NE) 3810b57cec5SDimitry Andric .add(MI->getOperand(2)); 3820b57cec5SDimitry Andric // The implicit use of CC is a killing use. 3830b57cec5SDimitry Andric BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo()); 3840b57cec5SDimitry Andric MI->eraseFromParent(); 3850b57cec5SDimitry Andric } 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric // Split MI into the comparison given by CompareOpcode followed 3880b57cec5SDimitry Andric // a BRCL on the result. 3890b57cec5SDimitry Andric void SystemZLongBranch::splitCompareBranch(MachineInstr *MI, 3900b57cec5SDimitry Andric unsigned CompareOpcode) { 3910b57cec5SDimitry Andric MachineBasicBlock *MBB = MI->getParent(); 3920b57cec5SDimitry Andric DebugLoc DL = MI->getDebugLoc(); 3930b57cec5SDimitry Andric BuildMI(*MBB, MI, DL, TII->get(CompareOpcode)) 3940b57cec5SDimitry Andric .add(MI->getOperand(0)) 3950b57cec5SDimitry Andric .add(MI->getOperand(1)); 3960b57cec5SDimitry Andric MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL)) 3970b57cec5SDimitry Andric .addImm(SystemZ::CCMASK_ICMP) 3980b57cec5SDimitry Andric .add(MI->getOperand(2)) 3990b57cec5SDimitry Andric .add(MI->getOperand(3)); 4000b57cec5SDimitry Andric // The implicit use of CC is a killing use. 4010b57cec5SDimitry Andric BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo()); 4020b57cec5SDimitry Andric MI->eraseFromParent(); 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric // Relax the branch described by Terminator. 4060b57cec5SDimitry Andric void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) { 4070b57cec5SDimitry Andric MachineInstr *Branch = Terminator.Branch; 4080b57cec5SDimitry Andric switch (Branch->getOpcode()) { 4090b57cec5SDimitry Andric case SystemZ::J: 4100b57cec5SDimitry Andric Branch->setDesc(TII->get(SystemZ::JG)); 4110b57cec5SDimitry Andric break; 4120b57cec5SDimitry Andric case SystemZ::BRC: 4130b57cec5SDimitry Andric Branch->setDesc(TII->get(SystemZ::BRCL)); 4140b57cec5SDimitry Andric break; 4150b57cec5SDimitry Andric case SystemZ::BRCT: 4160b57cec5SDimitry Andric splitBranchOnCount(Branch, SystemZ::AHI); 4170b57cec5SDimitry Andric break; 4180b57cec5SDimitry Andric case SystemZ::BRCTG: 4190b57cec5SDimitry Andric splitBranchOnCount(Branch, SystemZ::AGHI); 4200b57cec5SDimitry Andric break; 4210b57cec5SDimitry Andric case SystemZ::CRJ: 4220b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CR); 4230b57cec5SDimitry Andric break; 4240b57cec5SDimitry Andric case SystemZ::CGRJ: 4250b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CGR); 4260b57cec5SDimitry Andric break; 4270b57cec5SDimitry Andric case SystemZ::CIJ: 4280b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CHI); 4290b57cec5SDimitry Andric break; 4300b57cec5SDimitry Andric case SystemZ::CGIJ: 4310b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CGHI); 4320b57cec5SDimitry Andric break; 4330b57cec5SDimitry Andric case SystemZ::CLRJ: 4340b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CLR); 4350b57cec5SDimitry Andric break; 4360b57cec5SDimitry Andric case SystemZ::CLGRJ: 4370b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CLGR); 4380b57cec5SDimitry Andric break; 4390b57cec5SDimitry Andric case SystemZ::CLIJ: 4400b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CLFI); 4410b57cec5SDimitry Andric break; 4420b57cec5SDimitry Andric case SystemZ::CLGIJ: 4430b57cec5SDimitry Andric splitCompareBranch(Branch, SystemZ::CLGFI); 4440b57cec5SDimitry Andric break; 4450b57cec5SDimitry Andric default: 4460b57cec5SDimitry Andric llvm_unreachable("Unrecognized branch"); 4470b57cec5SDimitry Andric } 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric Terminator.Size += Terminator.ExtraRelaxSize; 4500b57cec5SDimitry Andric Terminator.ExtraRelaxSize = 0; 4510b57cec5SDimitry Andric Terminator.Branch = nullptr; 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric ++LongBranches; 4540b57cec5SDimitry Andric } 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric // Run a shortening pass and relax any branches that need to be relaxed. 4570b57cec5SDimitry Andric void SystemZLongBranch::relaxBranches() { 4580b57cec5SDimitry Andric SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin(); 4598bcb0991SDimitry Andric BlockPosition Position(Log2(MF->getAlignment())); 4600b57cec5SDimitry Andric for (auto &Block : MBBs) { 4610b57cec5SDimitry Andric skipNonTerminators(Position, Block); 4620b57cec5SDimitry Andric for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) { 4630b57cec5SDimitry Andric assert(Position.Address <= TI->Address && 4640b57cec5SDimitry Andric "Addresses shouldn't go forwards"); 4650b57cec5SDimitry Andric if (mustRelaxBranch(*TI, Position.Address)) 4660b57cec5SDimitry Andric relaxBranch(*TI); 4670b57cec5SDimitry Andric skipTerminator(Position, *TI, false); 4680b57cec5SDimitry Andric ++TI; 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric } 4710b57cec5SDimitry Andric } 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric bool SystemZLongBranch::runOnMachineFunction(MachineFunction &F) { 4740b57cec5SDimitry Andric TII = static_cast<const SystemZInstrInfo *>(F.getSubtarget().getInstrInfo()); 4750b57cec5SDimitry Andric MF = &F; 4760b57cec5SDimitry Andric uint64_t Size = initMBBInfo(); 4770b57cec5SDimitry Andric if (Size <= MaxForwardRange || !mustRelaxABranch()) 4780b57cec5SDimitry Andric return false; 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric setWorstCaseAddresses(); 4810b57cec5SDimitry Andric relaxBranches(); 4820b57cec5SDimitry Andric return true; 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric FunctionPass *llvm::createSystemZLongBranchPass(SystemZTargetMachine &TM) { 486*04eeddc0SDimitry Andric return new SystemZLongBranch(); 4870b57cec5SDimitry Andric } 488