HexagonFixupHwLoops.cpp revision 249259
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
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}
184