30#define DEBUG_TYPE "hexagon-brelax"
48 bool runOnMachineFunction(MachineFunction &MF)
override;
50 StringRef getPassName()
const override {
51 return "Hexagon Branch Relaxation";
54 void getAnalysisUsage(AnalysisUsage &AU)
const override {
60 const HexagonInstrInfo *HII;
61 const HexagonRegisterInfo *HRI;
63 bool relaxBranches(MachineFunction &MF);
64 void computeOffset(MachineFunction &MF,
65 DenseMap<MachineBasicBlock*, unsigned> &BlockToInstOffset);
66 bool reGenerateBranch(MachineFunction &MF,
67 DenseMap<MachineBasicBlock*, unsigned> &BlockToInstOffset);
68 bool isJumpOutOfRange(MachineInstr &
MI,
69 DenseMap<MachineBasicBlock*, unsigned> &BlockToInstOffset);
72 char HexagonBranchRelaxation::ID = 0;
77 "Hexagon Branch Relaxation",
false,
false)
80 return new HexagonBranchRelaxation();
83bool HexagonBranchRelaxation::runOnMachineFunction(
MachineFunction &MF) {
87 HII = HST.getInstrInfo();
88 HRI = HST.getRegisterInfo();
95void HexagonBranchRelaxation::computeOffset(MachineFunction &MF,
96 DenseMap<MachineBasicBlock*, unsigned> &OffsetMap) {
98 unsigned InstOffset = 0;
100 if (
B.getAlignment() !=
Align(1)) {
104 InstOffset =
alignTo(InstOffset,
B.getAlignment());
106 OffsetMap[&
B] = InstOffset;
107 for (
auto &
MI :
B.instrs()) {
108 InstOffset += HII->getSize(
MI);
110 if (
MI.isBranch() && HII->isExtendable(
MI))
121bool HexagonBranchRelaxation::relaxBranches(MachineFunction &MF) {
125 DenseMap<MachineBasicBlock*, unsigned> BlockToInstOffset;
126 computeOffset(MF, BlockToInstOffset);
128 return reGenerateBranch(MF, BlockToInstOffset);
135bool HexagonBranchRelaxation::isJumpOutOfRange(MachineInstr &
MI,
136 DenseMap<MachineBasicBlock*, unsigned> &BlockToInstOffset) {
137 MachineBasicBlock &
B = *
MI.getParent();
138 auto FirstTerm =
B.getFirstInstrTerminator();
139 if (FirstTerm ==
B.instr_end())
142 if (HII->isExtended(
MI))
145 unsigned InstOffset = BlockToInstOffset[&
B];
146 unsigned Distance = 0;
153 MachineBasicBlock *
TBB =
nullptr, *FBB =
nullptr;
157 if (HII->analyzeBranch(
B,
TBB, FBB,
Cond,
false)) {
161 if (HII->isNewValueJump(*FirstTerm))
162 TBB = FirstTerm->getOperand(HII->getCExtOpNum(*FirstTerm)).getMBB();
164 if (
TBB && &
MI == &*FirstTerm) {
165 Distance = std::abs((
long long)InstOffset - BlockToInstOffset[
TBB])
167 return !HII->isJumpWithinBranchRange(*FirstTerm, Distance);
171 auto SecondTerm = std::next(FirstTerm);
172 assert(SecondTerm !=
B.instr_end() &&
173 (SecondTerm->isBranch() || SecondTerm->isCall()) &&
174 "Bad second terminator");
175 if (&
MI != &*SecondTerm)
178 Distance = std::abs((
long long)InstOffset - BlockToInstOffset[FBB])
180 return !HII->isJumpWithinBranchRange(*SecondTerm, Distance);
185bool HexagonBranchRelaxation::reGenerateBranch(MachineFunction &MF,
186 DenseMap<MachineBasicBlock*, unsigned> &BlockToInstOffset) {
191 if (!
MI.isBranch() || !isJumpOutOfRange(
MI, BlockToInstOffset))
194 << HII->isExtendable(
MI) <<
") isConstExtended("
195 << HII->isConstExtended(
MI) <<
") " <<
MI);
199 if (!HII->isExtendable(
MI) && !HII->isExtended(
MI)) {
200 LLVM_DEBUG(
dbgs() <<
"\tUnderimplemented relax branch instruction.\n");
203 int ExtOpNum = HII->getCExtOpNum(
MI);
204 MachineOperand &MO =
MI.getOperand(ExtOpNum);
208 assert(MO.
isMBB() &&
"Branch with unknown expandable field type");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseMap class.
static cl::opt< uint32_t > BranchRelaxSafetyBuffer("branch-relax-safety-buffer", cl::init(200), cl::Hidden, cl::desc("safety buffer size"))
#define HEXAGON_INSTR_SIZE
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file defines the SmallVector class.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
FunctionPass class - This class is used to implement most global optimizations.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void addTargetFlag(unsigned F)
bool isMBB() const
isMBB - Tests if this is a MO_MachineBasicBlock operand.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createHexagonBranchRelaxation()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.