1 //===---- HexagonFixupHwLoops.cpp - Fixup HW loops too far from LOOPn. ----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 // The loop start address in the LOOPn instruction is encoded as a distance
9 // from the LOOPn instruction itself. If the start address is too far from
10 // the LOOPn instruction, the loop needs to be set up manually, i.e. via
11 // direct transfers to SAn and LCn.
12 // This pass will identify and convert such LOOPn instructions to a proper
14 //===----------------------------------------------------------------------===//
17 #include "llvm/ADT/DenseMap.h"
19 #include "HexagonTargetMachine.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/CodeGen/MachineFunctionPass.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/Passes.h"
24 #include "llvm/CodeGen/RegisterScavenging.h"
25 #include "llvm/PassSupport.h"
26 #include "llvm/Target/TargetInstrInfo.h"
31 void initializeHexagonFixupHwLoopsPass(PassRegistry&);
35 struct HexagonFixupHwLoops : public MachineFunctionPass {
39 HexagonFixupHwLoops() : MachineFunctionPass(ID) {
40 initializeHexagonFixupHwLoopsPass(*PassRegistry::getPassRegistry());
43 bool runOnMachineFunction(MachineFunction &MF) override;
45 const char *getPassName() const override {
46 return "Hexagon Hardware Loop Fixup";
49 void getAnalysisUsage(AnalysisUsage &AU) const override {
51 MachineFunctionPass::getAnalysisUsage(AU);
55 /// \brief Maximum distance between the loop instr and the basic block.
57 static const unsigned MAX_LOOP_DISTANCE = 200;
59 /// \brief Check the offset between each loop instruction and
60 /// the loop basic block to determine if we can use the LOOP instruction
61 /// or if we need to set the LC/SA registers explicitly.
62 bool fixupLoopInstrs(MachineFunction &MF);
64 /// \brief Add the instruction to set the LC and SA registers explicitly.
65 void convertLoopInstr(MachineFunction &MF,
66 MachineBasicBlock::iterator &MII,
71 char HexagonFixupHwLoops::ID = 0;
74 INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",
75 "Hexagon Hardware Loops Fixup", false, false)
77 FunctionPass *llvm::createHexagonFixupHwLoops() {
78 return new HexagonFixupHwLoops();
82 /// \brief Returns true if the instruction is a hardware loop instruction.
83 static bool isHardwareLoop(const MachineInstr *MI) {
84 return MI->getOpcode() == Hexagon::LOOP0_r ||
85 MI->getOpcode() == Hexagon::LOOP0_i;
89 bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
90 bool Changed = fixupLoopInstrs(MF);
95 /// \brief For Hexagon, if the loop label is to far from the
96 /// loop instruction then we need to set the LC0 and SA0 registers
97 /// explicitly instead of using LOOP(start,count). This function
98 /// checks the distance, and generates register assignments if needed.
100 /// This function makes two passes over the basic blocks. The first
101 /// pass computes the offset of the basic block from the start.
102 /// The second pass checks all the loop instructions.
103 bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
105 // Offset of the current instruction from the start.
106 unsigned InstOffset = 0;
107 // Map for each basic block to it's first instruction.
108 DenseMap<MachineBasicBlock*, unsigned> BlockToInstOffset;
110 // First pass - compute the offset of each basic block.
111 for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
112 MBB != MBBe; ++MBB) {
113 BlockToInstOffset[MBB] = InstOffset;
114 InstOffset += (MBB->size() * 4);
117 // Second pass - check each loop instruction to see if it needs to
120 bool Changed = false;
123 // Loop over all the basic blocks.
124 for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
125 MBB != MBBe; ++MBB) {
126 InstOffset = BlockToInstOffset[MBB];
127 RS.enterBasicBlock(MBB);
129 // Loop over all the instructions.
130 MachineBasicBlock::iterator MIE = MBB->end();
131 MachineBasicBlock::iterator MII = MBB->begin();
133 if (isHardwareLoop(MII)) {
135 assert(MII->getOperand(0).isMBB() &&
136 "Expect a basic block as loop operand");
137 int Sub = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()];
138 unsigned Dist = Sub > 0 ? Sub : -Sub;
139 if (Dist > MAX_LOOP_DISTANCE) {
140 // Convert to explicity setting LC0 and SA0.
141 convertLoopInstr(MF, MII, RS);
142 MII = MBB->erase(MII);
158 /// \brief convert a loop instruction to a sequence of instructions that
159 /// set the LC0 and SA0 register explicitly.
160 void HexagonFixupHwLoops::convertLoopInstr(MachineFunction &MF,
161 MachineBasicBlock::iterator &MII,
163 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
164 MachineBasicBlock *MBB = MII->getParent();
165 DebugLoc DL = MII->getDebugLoc();
166 unsigned Scratch = RS.scavengeRegister(&Hexagon::IntRegsRegClass, MII, 0);
168 // First, set the LC0 with the trip count.
169 if (MII->getOperand(1).isReg()) {
170 // Trip count is a register
171 BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
172 .addReg(MII->getOperand(1).getReg());
174 // Trip count is an immediate.
175 BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFRI), Scratch)
176 .addImm(MII->getOperand(1).getImm());
177 BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
180 // Then, set the SA0 with the loop start address.
181 BuildMI(*MBB, MII, DL, TII->get(Hexagon::CONST32_Label), Scratch)
182 .addMBB(MII->getOperand(0).getMBB());
183 BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::SA0)