]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/llvm/lib/Target/Hexagon/HexagonFixupHwLoops.cpp
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / llvm / lib / Target / Hexagon / HexagonFixupHwLoops.cpp
1 //===---- 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
28 using namespace llvm;
29
30 namespace llvm {
31   void initializeHexagonFixupHwLoopsPass(PassRegistry&);
32 }
33
34 namespace {
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
72 INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",
73                 "Hexagon Hardware Loops Fixup", false, false)
74
75 FunctionPass *llvm::createHexagonFixupHwLoops() {
76   return new HexagonFixupHwLoops();
77 }
78
79
80 /// \brief Returns true if the instruction is a hardware loop instruction.
81 static bool isHardwareLoop(const MachineInstr *MI) {
82   return MI->getOpcode() == Hexagon::LOOP0_r ||
83          MI->getOpcode() == Hexagon::LOOP0_i;
84 }
85
86
87 bool 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.
101 bool 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.
158 void 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 }