LLVM  3.7.0
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 instruction needs to use a constant extender.
11 // This pass will identify and convert such LOOPn instructions to a proper
12 // form.
13 //===----------------------------------------------------------------------===//
14 
15 
16 #include "llvm/ADT/DenseMap.h"
17 #include "Hexagon.h"
18 #include "HexagonTargetMachine.h"
22 #include "llvm/CodeGen/Passes.h"
23 #include "llvm/PassSupport.h"
25 
26 using namespace llvm;
27 
29  "hexagon-loop-range", cl::Hidden, cl::init(200),
30  cl::desc("Restrict range of loopN instructions (testing only)"));
31 
32 namespace llvm {
35 }
36 
37 namespace {
38  struct HexagonFixupHwLoops : public MachineFunctionPass {
39  public:
40  static char ID;
41 
42  HexagonFixupHwLoops() : MachineFunctionPass(ID) {
44  }
45 
46  bool runOnMachineFunction(MachineFunction &MF) override;
47 
48  const char *getPassName() const override {
49  return "Hexagon Hardware Loop Fixup";
50  }
51 
52  void getAnalysisUsage(AnalysisUsage &AU) const override {
53  AU.setPreservesCFG();
55  }
56 
57  private:
58  /// \brief Check the offset between each loop instruction and
59  /// the loop basic block to determine if we can use the LOOP instruction
60  /// or if we need to set the LC/SA registers explicitly.
61  bool fixupLoopInstrs(MachineFunction &MF);
62 
63  /// \brief Replace loop instruction with the constant extended
64  /// version if the loop label is too far from the loop instruction.
65  void useExtLoopInstr(MachineFunction &MF,
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 /// \brief Returns true if the instruction is a hardware loop instruction.
80 static bool isHardwareLoop(const MachineInstr *MI) {
81  return MI->getOpcode() == Hexagon::J2_loop0r ||
82  MI->getOpcode() == Hexagon::J2_loop0i ||
83  MI->getOpcode() == Hexagon::J2_loop1r ||
84  MI->getOpcode() == Hexagon::J2_loop1i;
85 }
86 
87 bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
88  return fixupLoopInstrs(MF);
89 }
90 
91 /// \brief For Hexagon, if the loop label is to far from the
92 /// loop instruction then we need to set the LC0 and SA0 registers
93 /// explicitly instead of using LOOP(start,count). This function
94 /// checks the distance, and generates register assignments if needed.
95 ///
96 /// This function makes two passes over the basic blocks. The first
97 /// pass computes the offset of the basic block from the start.
98 /// The second pass checks all the loop instructions.
99 bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
100 
101  // Offset of the current instruction from the start.
102  unsigned InstOffset = 0;
103  // Map for each basic block to it's first instruction.
105 
106  const HexagonInstrInfo *HII =
107  static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo());
108 
109  // First pass - compute the offset of each basic block.
110  for (const MachineBasicBlock &MBB : MF) {
111  if (MBB.getAlignment()) {
112  // Although we don't know the exact layout of the final code, we need
113  // to account for alignment padding somehow. This heuristic pads each
114  // aligned basic block according to the alignment value.
115  int ByteAlign = (1u << MBB.getAlignment()) - 1;
116  InstOffset = (InstOffset + ByteAlign) & ~(ByteAlign);
117  }
118 
119  BlockToInstOffset[&MBB] = InstOffset;
120  for (const MachineInstr &MI : MBB)
121  InstOffset += HII->getSize(&MI);
122  }
123 
124  // Second pass - check each loop instruction to see if it needs to be
125  // converted.
126  InstOffset = 0;
127  bool Changed = false;
128  for (MachineBasicBlock &MBB : MF) {
129  InstOffset = BlockToInstOffset[&MBB];
130 
131  // Loop over all the instructions.
133  MachineBasicBlock::iterator MIE = MBB.end();
134  while (MII != MIE) {
135  InstOffset += HII->getSize(&*MII);
136  if (MII->isDebugValue()) {
137  ++MII;
138  continue;
139  }
140  if (isHardwareLoop(MII)) {
141  assert(MII->getOperand(0).isMBB() &&
142  "Expect a basic block as loop operand");
143  int diff = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()];
144  if ((unsigned)abs(diff) > MaxLoopRange) {
145  useExtLoopInstr(MF, MII);
146  MII = MBB.erase(MII);
147  Changed = true;
148  } else {
149  ++MII;
150  }
151  } else {
152  ++MII;
153  }
154  }
155  }
156 
157  return Changed;
158 }
159 
160 /// \brief Replace loop instructions with the constant extended version.
161 void HexagonFixupHwLoops::useExtLoopInstr(MachineFunction &MF,
164  MachineBasicBlock *MBB = MII->getParent();
165  DebugLoc DL = MII->getDebugLoc();
167  unsigned newOp;
168  switch (MII->getOpcode()) {
169  case Hexagon::J2_loop0r:
170  newOp = Hexagon::J2_loop0rext;
171  break;
172  case Hexagon::J2_loop0i:
173  newOp = Hexagon::J2_loop0iext;
174  break;
175  case Hexagon::J2_loop1r:
176  newOp = Hexagon::J2_loop1rext;
177  break;
178  case Hexagon::J2_loop1i:
179  newOp = Hexagon::J2_loop1iext;
180  break;
181  default:
182  llvm_unreachable("Invalid Hardware Loop Instruction.");
183  }
184  MIB = BuildMI(*MBB, MII, DL, TII->get(newOp));
185 
186  for (unsigned i = 0; i < MII->getNumOperands(); ++i)
187  MIB.addOperand(MII->getOperand(i));
188 }
const MachineFunction * getParent() const
getParent - Return the MachineFunction containing this basic block.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static cl::opt< unsigned > MaxLoopRange("hexagon-loop-range", cl::Hidden, cl::init(200), cl::desc("Restrict range of loopN instructions (testing only)"))
void initializeHexagonFixupHwLoopsPass(PassRegistry &)
A debug info location.
Definition: DebugLoc.h:34
static bool isHardwareLoop(const MachineInstr *MI)
Returns true if the instruction is a hardware loop instruction.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getSize(const MachineInstr *MI) const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:267
TargetInstrInfo - Interface to description of machine instruction set.
bundle_iterator< MachineInstr, instr_iterator > iterator
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:325
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:294
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
BuildMI - Builder interface.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:45
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:263
Representation of each machine instruction.
Definition: MachineInstr.h:51
FunctionPass * createHexagonFixupHwLoops()
APFloat abs(APFloat X)
Returns the absolute value of the argument.
Definition: APFloat.h:651
virtual const TargetInstrInfo * getInstrInfo() const
const MachineInstrBuilder & addOperand(const MachineOperand &MO) const
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:41
INITIALIZE_PASS(HexagonFixupHwLoops,"hwloopsfixup","Hexagon Hardware Loops Fixup", false, false) FunctionPass *llvm