HexagonFixupHwLoops.cpp revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
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
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    bool runOnMachineFunction(MachineFunction &MF) override;
44
45    const char *getPassName() const override {
46      return "Hexagon Hardware Loop Fixup";
47    }
48
49    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
74INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",
75                "Hexagon Hardware Loops Fixup", false, false)
76
77FunctionPass *llvm::createHexagonFixupHwLoops() {
78  return new HexagonFixupHwLoops();
79}
80
81
82/// \brief Returns true if the instruction is a hardware loop instruction.
83static bool isHardwareLoop(const MachineInstr *MI) {
84  return MI->getOpcode() == Hexagon::LOOP0_r ||
85         MI->getOpcode() == Hexagon::LOOP0_i;
86}
87
88
89bool 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.
103bool 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.
160void 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