//===-- PPCBranchSelector.cpp - Emit long conditional branches ------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains a pass that scans a machine function to determine which // conditional branches need more than 16 bits of displacement to reach their // target basic block. It does this in two passes; a calculation of basic block // positions pass, and a branch pseudo op to machine branch opcode pass. This // pass should be run last, just before the assembly printer. // //===----------------------------------------------------------------------===// #include "MCTargetDesc/PPCPredicates.h" #include "PPC.h" #include "PPCInstrBuilder.h" #include "PPCInstrInfo.h" #include "PPCSubtarget.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/Support/MathExtras.h" #include "llvm/Target/TargetMachine.h" #include <algorithm> usingnamespacellvm; #define DEBUG_TYPE … STATISTIC(NumExpanded, "Number of branches expanded to long format"); STATISTIC(NumPrefixed, "Number of prefixed instructions"); STATISTIC(NumPrefixedAligned, "Number of prefixed instructions that have been aligned"); namespace { struct PPCBSel : public MachineFunctionPass { … }; char PPCBSel::ID = …; } INITIALIZE_PASS(…) /// createPPCBranchSelectionPass - returns an instance of the Branch Selection /// Pass /// FunctionPass *llvm::createPPCBranchSelectionPass() { … } /// In order to make MBB aligned, we need to add an adjustment value to the /// original Offset. unsigned PPCBSel::GetAlignmentAdjustment(MachineBasicBlock &MBB, unsigned Offset) { … } /// We need to be careful about the offset of the first block in the function /// because it might not have the function's alignment. This happens because, /// under the ELFv2 ABI, for functions which require a TOC pointer, we add a /// two-instruction sequence to the start of the function. /// Note: This needs to be synchronized with the check in /// PPCLinuxAsmPrinter::EmitFunctionBodyStart. static inline unsigned GetInitialOffset(MachineFunction &Fn) { … } /// Measure each MBB and compute a size for the entire function. unsigned PPCBSel::ComputeBlockSizes(MachineFunction &Fn) { … } /// Modify the basic block align adjustment. void PPCBSel::modifyAdjustment(MachineFunction &Fn) { … } /// Determine the offset from the branch in Src block to the Dest block. /// BrOffset is the offset of the branch instruction inside Src block. int PPCBSel::computeBranchSize(MachineFunction &Fn, const MachineBasicBlock *Src, const MachineBasicBlock *Dest, unsigned BrOffset) { … } bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) { … }