• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Hexagon.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"
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 
HexagonFixupHwLoops__anonb5d5dffa0111::HexagonFixupHwLoops39     HexagonFixupHwLoops() : MachineFunctionPass(ID) {
40       initializeHexagonFixupHwLoopsPass(*PassRegistry::getPassRegistry());
41     }
42 
43     bool runOnMachineFunction(MachineFunction &MF) override;
44 
getPassName__anonb5d5dffa0111::HexagonFixupHwLoops45     const char *getPassName() const override {
46       return "Hexagon Hardware Loop Fixup";
47     }
48 
getAnalysisUsage__anonb5d5dffa0111::HexagonFixupHwLoops49     void getAnalysisUsage(AnalysisUsage &AU) const override {
50       AU.setPreservesCFG();
51       MachineFunctionPass::getAnalysisUsage(AU);
52     }
53 
54   private:
55     /// \brief Maximum distance between the loop instr and the basic block.
56     /// Just an estimate.
57     static const unsigned MAX_LOOP_DISTANCE = 200;
58 
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);
63 
64     /// \brief Add the instruction to set the LC and SA registers explicitly.
65     void convertLoopInstr(MachineFunction &MF,
66                           MachineBasicBlock::iterator &MII,
67                           RegScavenger &RS);
68 
69   };
70 
71   char HexagonFixupHwLoops::ID = 0;
72 }
73 
74 INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",
75                 "Hexagon Hardware Loops Fixup", false, false)
76 
createHexagonFixupHwLoops()77 FunctionPass *llvm::createHexagonFixupHwLoops() {
78   return new HexagonFixupHwLoops();
79 }
80 
81 
82 /// \brief Returns true if the instruction is a hardware loop instruction.
isHardwareLoop(const MachineInstr * MI)83 static bool isHardwareLoop(const MachineInstr *MI) {
84   return MI->getOpcode() == Hexagon::LOOP0_r ||
85          MI->getOpcode() == Hexagon::LOOP0_i;
86 }
87 
88 
runOnMachineFunction(MachineFunction & MF)89 bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
90   bool Changed = fixupLoopInstrs(MF);
91   return Changed;
92 }
93 
94 
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.
99 ///
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.
fixupLoopInstrs(MachineFunction & MF)103 bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
104 
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;
109 
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);
115   }
116 
117   // Second pass - check each loop instruction to see if it needs to
118   // be converted.
119   InstOffset = 0;
120   bool Changed = false;
121   RegScavenger RS;
122 
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);
128 
129     // Loop over all the instructions.
130     MachineBasicBlock::iterator MIE = MBB->end();
131     MachineBasicBlock::iterator MII = MBB->begin();
132     while (MII != MIE) {
133       if (isHardwareLoop(MII)) {
134         RS.forward(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);
143           Changed = true;
144         } else {
145           ++MII;
146         }
147       } else {
148         ++MII;
149       }
150       InstOffset += 4;
151     }
152   }
153 
154   return Changed;
155 }
156 
157 
158 /// \brief convert a loop instruction to a sequence of instructions that
159 /// set the LC0 and SA0 register explicitly.
convertLoopInstr(MachineFunction & MF,MachineBasicBlock::iterator & MII,RegScavenger & RS)160 void HexagonFixupHwLoops::convertLoopInstr(MachineFunction &MF,
161                                            MachineBasicBlock::iterator &MII,
162                                            RegScavenger &RS) {
163   const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
164   MachineBasicBlock *MBB = MII->getParent();
165   DebugLoc DL = MII->getDebugLoc();
166   unsigned Scratch = RS.scavengeRegister(&Hexagon::IntRegsRegClass, MII, 0);
167 
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());
173   } else {
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)
178       .addReg(Scratch);
179   }
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)
184     .addReg(Scratch);
185 }
186