LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HexagonFixupHwLoops.cpp
Go to the documentation of this file.
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"
21 #include "llvm/CodeGen/Passes.h"
23 #include "llvm/PassSupport.h"
25 #include "Hexagon.h"
26 #include "HexagonTargetMachine.h"
27 
28 using namespace llvm;
29 
30 namespace llvm {
32 }
33 
34 namespace {
35  struct HexagonFixupHwLoops : public MachineFunctionPass {
36  public:
37  static char ID;
38 
39  HexagonFixupHwLoops() : MachineFunctionPass(ID) {
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();
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,
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 
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,
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 }
const MachineFunction * getParent() const
static PassRegistry * getPassRegistry()
void initializeHexagonFixupHwLoopsPass(PassRegistry &)
static bool isHardwareLoop(const MachineInstr *MI)
Returns true if the instruction is a hardware loop instruction.
const HexagonInstrInfo * TII
ID
LLVM Calling Convention Representation.
Definition: CallingConv.h:26
void forward()
forward - Move the internal MBB iterator and update register states.
int getOpcode() const
Definition: MachineInstr.h:261
FunctionPass * createHexagonFixupHwLoops()
void enterBasicBlock(MachineBasicBlock *mbb)
bundle_iterator< MachineInstr, instr_iterator > iterator
const MCInstrInfo & MII
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
const MCInstrDesc & get(unsigned Opcode) const
Definition: MCInstrInfo.h:48
virtual const TargetInstrInfo * getInstrInfo() const
void setPreservesCFG()
Definition: Pass.cpp:249
virtual void getAnalysisUsage(AnalysisUsage &AU) const
const TargetMachine & getTarget() const
BasicBlockListType::iterator iterator
INITIALIZE_PASS(HexagonFixupHwLoops,"hwloopsfixup","Hexagon Hardware Loops Fixup", false, false) FunctionPass *llvm
unsigned scavengeRegister(const TargetRegisterClass *RegClass, MachineBasicBlock::iterator I, int SPAdj)