blob: 240cc95666480ce1c5da62d941eefcb1f5ef19d7 [file] [log] [blame]
Krzysztof Parzyszek71490fa2013-02-11 21:37:55 +00001//===---- HexagonFixupHwLoops.cpp - Fixup HW loops too far from LOOPn. ----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
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
13// form.
14//===----------------------------------------------------------------------===//
15
16
17#include "llvm/ADT/DenseMap.h"
18#include "llvm/CodeGen/MachineFunction.h"
19#include "llvm/CodeGen/MachineFunctionPass.h"
20#include "llvm/CodeGen/MachineInstrBuilder.h"
21#include "llvm/CodeGen/Passes.h"
22#include "llvm/CodeGen/RegisterScavenging.h"
23#include "llvm/PassSupport.h"
24#include "llvm/Target/TargetInstrInfo.h"
25#include "Hexagon.h"
26#include "HexagonTargetMachine.h"
27
28using namespace llvm;
29
30namespace llvm {
31 void initializeHexagonFixupHwLoopsPass(PassRegistry&);
32}
33
34namespace {
35 struct HexagonFixupHwLoops : public MachineFunctionPass {
36 public:
37 static char ID;
38
39 HexagonFixupHwLoops() : MachineFunctionPass(ID) {
40 initializeHexagonFixupHwLoopsPass(*PassRegistry::getPassRegistry());
41 }
42
43 virtual bool runOnMachineFunction(MachineFunction &MF);
44
45 const char *getPassName() const { return "Hexagon Hardware Loop Fixup"; }
46
47 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
48 AU.setPreservesCFG();
49 MachineFunctionPass::getAnalysisUsage(AU);
50 }
51
52 private:
53 /// \brief Maximum distance between the loop instr and the basic block.
54 /// Just an estimate.
55 static const unsigned MAX_LOOP_DISTANCE = 200;
56
57 /// \brief Check the offset between each loop instruction and
58 /// the loop basic block to determine if we can use the LOOP instruction
59 /// or if we need to set the LC/SA registers explicitly.
60 bool fixupLoopInstrs(MachineFunction &MF);
61
62 /// \brief Add the instruction to set the LC and SA registers explicitly.
63 void convertLoopInstr(MachineFunction &MF,
64 MachineBasicBlock::iterator &MII,
65 RegScavenger &RS);
66
67 };
68
69 char HexagonFixupHwLoops::ID = 0;
70}
71
72INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",
73 "Hexagon Hardware Loops Fixup", false, false)
74
75FunctionPass *llvm::createHexagonFixupHwLoops() {
76 return new HexagonFixupHwLoops();
77}
78
79
80/// \brief Returns true if the instruction is a hardware loop instruction.
81static bool isHardwareLoop(const MachineInstr *MI) {
82 return MI->getOpcode() == Hexagon::LOOP0_r ||
83 MI->getOpcode() == Hexagon::LOOP0_i;
84}
85
86
87bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
88 bool Changed = fixupLoopInstrs(MF);
89 return Changed;
90}
91
92
93/// \brief For Hexagon, if the loop label is to far from the
94/// loop instruction then we need to set the LC0 and SA0 registers
95/// explicitly instead of using LOOP(start,count). This function
96/// checks the distance, and generates register assignments if needed.
97///
98/// This function makes two passes over the basic blocks. The first
99/// pass computes the offset of the basic block from the start.
100/// The second pass checks all the loop instructions.
101bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
102
103 // Offset of the current instruction from the start.
104 unsigned InstOffset = 0;
105 // Map for each basic block to it's first instruction.
106 DenseMap<MachineBasicBlock*, unsigned> BlockToInstOffset;
107
108 // First pass - compute the offset of each basic block.
109 for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
110 MBB != MBBe; ++MBB) {
111 BlockToInstOffset[MBB] = InstOffset;
112 InstOffset += (MBB->size() * 4);
113 }
114
115 // Second pass - check each loop instruction to see if it needs to
116 // be converted.
117 InstOffset = 0;
118 bool Changed = false;
119 RegScavenger RS;
120
121 // Loop over all the basic blocks.
122 for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
123 MBB != MBBe; ++MBB) {
124 InstOffset = BlockToInstOffset[MBB];
125 RS.enterBasicBlock(MBB);
126
127 // Loop over all the instructions.
128 MachineBasicBlock::iterator MIE = MBB->end();
129 MachineBasicBlock::iterator MII = MBB->begin();
130 while (MII != MIE) {
131 if (isHardwareLoop(MII)) {
132 RS.forward(MII);
133 assert(MII->getOperand(0).isMBB() &&
134 "Expect a basic block as loop operand");
135 int Sub = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()];
136 unsigned Dist = Sub > 0 ? Sub : -Sub;
137 if (Dist > MAX_LOOP_DISTANCE) {
138 // Convert to explicity setting LC0 and SA0.
139 convertLoopInstr(MF, MII, RS);
140 MII = MBB->erase(MII);
141 Changed = true;
142 } else {
143 ++MII;
144 }
145 } else {
146 ++MII;
147 }
148 InstOffset += 4;
149 }
150 }
151
152 return Changed;
153}
154
155
156/// \brief convert a loop instruction to a sequence of instructions that
157/// set the LC0 and SA0 register explicitly.
158void HexagonFixupHwLoops::convertLoopInstr(MachineFunction &MF,
159 MachineBasicBlock::iterator &MII,
160 RegScavenger &RS) {
161 const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
162 MachineBasicBlock *MBB = MII->getParent();
163 DebugLoc DL = MII->getDebugLoc();
164 unsigned Scratch = RS.scavengeRegister(&Hexagon::IntRegsRegClass, MII, 0);
165
166 // First, set the LC0 with the trip count.
167 if (MII->getOperand(1).isReg()) {
168 // Trip count is a register
169 BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
170 .addReg(MII->getOperand(1).getReg());
171 } else {
172 // Trip count is an immediate.
173 BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFRI), Scratch)
174 .addImm(MII->getOperand(1).getImm());
175 BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
176 .addReg(Scratch);
177 }
178 // Then, set the SA0 with the loop start address.
179 BuildMI(*MBB, MII, DL, TII->get(Hexagon::CONST32_Label), Scratch)
180 .addMBB(MII->getOperand(0).getMBB());
181 BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::SA0)
182 .addReg(Scratch);
183}