LLVM  8.0.1
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 #include "Hexagon.h"
16 #include "HexagonTargetMachine.h"
17 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/CodeGen/Passes.h"
24 #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  MachineFunctionProperties getRequiredProperties() const override {
51  }
52 
53  StringRef getPassName() const override {
54  return "Hexagon Hardware Loop Fixup";
55  }
56 
57  void getAnalysisUsage(AnalysisUsage &AU) const override {
58  AU.setPreservesCFG();
60  }
61 
62  private:
63  /// Check the offset between each loop instruction and
64  /// the loop basic block to determine if we can use the LOOP instruction
65  /// or if we need to set the LC/SA registers explicitly.
66  bool fixupLoopInstrs(MachineFunction &MF);
67 
68  /// Replace loop instruction with the constant extended
69  /// version if the loop label is too far from the loop instruction.
70  void useExtLoopInstr(MachineFunction &MF,
72  };
73 
74  char HexagonFixupHwLoops::ID = 0;
75 }
76 
77 INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",
78  "Hexagon Hardware Loops Fixup", false, false)
79 
81  return new HexagonFixupHwLoops();
82 }
83 
84 /// Returns true if the instruction is a hardware loop instruction.
85 static bool isHardwareLoop(const MachineInstr &MI) {
86  return MI.getOpcode() == Hexagon::J2_loop0r ||
87  MI.getOpcode() == Hexagon::J2_loop0i ||
88  MI.getOpcode() == Hexagon::J2_loop1r ||
89  MI.getOpcode() == Hexagon::J2_loop1i;
90 }
91 
92 bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
93  if (skipFunction(MF.getFunction()))
94  return false;
95  return fixupLoopInstrs(MF);
96 }
97 
98 /// For Hexagon, if the loop label is to far from the
99 /// loop instruction then we need to set the LC0 and SA0 registers
100 /// explicitly instead of using LOOP(start,count). This function
101 /// checks the distance, and generates register assignments if needed.
102 ///
103 /// This function makes two passes over the basic blocks. The first
104 /// pass computes the offset of the basic block from the start.
105 /// The second pass checks all the loop instructions.
106 bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
107 
108  // Offset of the current instruction from the start.
109  unsigned InstOffset = 0;
110  // Map for each basic block to it's first instruction.
112 
113  const HexagonInstrInfo *HII =
114  static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo());
115 
116  // First pass - compute the offset of each basic block.
117  for (const MachineBasicBlock &MBB : MF) {
118  if (MBB.getAlignment()) {
119  // Although we don't know the exact layout of the final code, we need
120  // to account for alignment padding somehow. This heuristic pads each
121  // aligned basic block according to the alignment value.
122  int ByteAlign = (1u << MBB.getAlignment()) - 1;
123  InstOffset = (InstOffset + ByteAlign) & ~(ByteAlign);
124  }
125 
126  BlockToInstOffset[&MBB] = InstOffset;
127  for (const MachineInstr &MI : MBB)
128  InstOffset += HII->getSize(MI);
129  }
130 
131  // Second pass - check each loop instruction to see if it needs to be
132  // converted.
133  bool Changed = false;
134  for (MachineBasicBlock &MBB : MF) {
135  InstOffset = BlockToInstOffset[&MBB];
136 
137  // Loop over all the instructions.
138  MachineBasicBlock::iterator MII = MBB.begin();
139  MachineBasicBlock::iterator MIE = MBB.end();
140  while (MII != MIE) {
141  unsigned InstSize = HII->getSize(*MII);
142  if (MII->isMetaInstruction()) {
143  ++MII;
144  continue;
145  }
146  if (isHardwareLoop(*MII)) {
147  assert(MII->getOperand(0).isMBB() &&
148  "Expect a basic block as loop operand");
149  MachineBasicBlock *TargetBB = MII->getOperand(0).getMBB();
150  unsigned Diff = AbsoluteDifference(InstOffset,
151  BlockToInstOffset[TargetBB]);
152  if (Diff > MaxLoopRange) {
153  useExtLoopInstr(MF, MII);
154  MII = MBB.erase(MII);
155  Changed = true;
156  } else {
157  ++MII;
158  }
159  } else {
160  ++MII;
161  }
162  InstOffset += InstSize;
163  }
164  }
165 
166  return Changed;
167 }
168 
169 /// Replace loop instructions with the constant extended version.
170 void HexagonFixupHwLoops::useExtLoopInstr(MachineFunction &MF,
173  MachineBasicBlock *MBB = MII->getParent();
174  DebugLoc DL = MII->getDebugLoc();
176  unsigned newOp;
177  switch (MII->getOpcode()) {
178  case Hexagon::J2_loop0r:
179  newOp = Hexagon::J2_loop0rext;
180  break;
181  case Hexagon::J2_loop0i:
182  newOp = Hexagon::J2_loop0iext;
183  break;
184  case Hexagon::J2_loop1r:
185  newOp = Hexagon::J2_loop1rext;
186  break;
187  case Hexagon::J2_loop1i:
188  newOp = Hexagon::J2_loop1iext;
189  break;
190  default:
191  llvm_unreachable("Invalid Hardware Loop Instruction.");
192  }
193  MIB = BuildMI(*MBB, MII, DL, TII->get(newOp));
194 
195  for (unsigned i = 0; i < MII->getNumOperands(); ++i)
196  MIB.add(MII->getOperand(i));
197 }
INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup", "Hexagon Hardware Loops Fixup", false, false) FunctionPass *llvm
const MachineInstrBuilder & add(const MachineOperand &MO) const
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This class represents lattice values for constants.
Definition: AllocatorList.h:24
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
unsigned getSize(const MachineInstr &MI) const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:409
virtual const TargetInstrInfo * getInstrInfo() const
TargetInstrInfo - Interface to description of machine instruction set.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:423
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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:285
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:286
const Function & getFunction() const
Return the LLVM function that this machine code represents.
MachineFunctionProperties & set(Property P)
Representation of each machine instruction.
Definition: MachineInstr.h:64
static bool isHardwareLoop(const MachineInstr &MI)
Returns true if the instruction is a hardware loop instruction.
FunctionPass * createHexagonFixupHwLoops()
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:45
std::enable_if< std::is_unsigned< T >::value, T >::type AbsoluteDifference(T X, T Y)
Subtract two unsigned integers, X and Y, of type T and return the absolute value of the result...
Definition: MathExtras.h:767
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:39
Properties which a MachineFunction may have at a given point in time.