LLVM 19.0.0git
HexagonFixupHwLoops.cpp
Go to the documentation of this file.
1//===---- HexagonFixupHwLoops.cpp - Fixup HW loops too far from LOOPn. ----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7// The loop start address in the LOOPn instruction is encoded as a distance
8// from the LOOPn instruction itself. If the start address is too far from
9// the LOOPn instruction, the instruction needs to use a constant extender.
10// This pass will identify and convert such LOOPn instructions to a proper
11// form.
12//===----------------------------------------------------------------------===//
13
14#include "Hexagon.h"
16#include "llvm/ADT/DenseMap.h"
20#include "llvm/CodeGen/Passes.h"
23#include "llvm/Pass.h"
24
25using namespace llvm;
26
28 "hexagon-loop-range", cl::Hidden, cl::init(200),
29 cl::desc("Restrict range of loopN instructions (testing only)"));
30
31namespace llvm {
34}
35
36namespace {
37 struct HexagonFixupHwLoops : public MachineFunctionPass {
38 public:
39 static char ID;
40
41 HexagonFixupHwLoops() : MachineFunctionPass(ID) {
43 }
44
45 bool runOnMachineFunction(MachineFunction &MF) override;
46
49 MachineFunctionProperties::Property::NoVRegs);
50 }
51
52 StringRef getPassName() const override {
53 return "Hexagon Hardware Loop Fixup";
54 }
55
56 void getAnalysisUsage(AnalysisUsage &AU) const override {
57 AU.setPreservesCFG();
59 }
60
61 private:
62 /// Check the offset between each loop instruction and
63 /// the loop basic block to determine if we can use the LOOP instruction
64 /// or if we need to set the LC/SA registers explicitly.
65 bool fixupLoopInstrs(MachineFunction &MF);
66
67 /// Replace loop instruction with the constant extended
68 /// version if the loop label is too far from the loop instruction.
69 void useExtLoopInstr(MachineFunction &MF,
71 };
72
73 char HexagonFixupHwLoops::ID = 0;
74}
75
76INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",
77 "Hexagon Hardware Loops Fixup", false, false)
78
80 return new HexagonFixupHwLoops();
81}
82
83/// Returns true if the instruction is a hardware loop instruction.
84static bool isHardwareLoop(const MachineInstr &MI) {
85 return MI.getOpcode() == Hexagon::J2_loop0r ||
86 MI.getOpcode() == Hexagon::J2_loop0i ||
87 MI.getOpcode() == Hexagon::J2_loop1r ||
88 MI.getOpcode() == Hexagon::J2_loop1i;
89}
90
91bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
92 if (skipFunction(MF.getFunction()))
93 return false;
94 return fixupLoopInstrs(MF);
95}
96
97/// For Hexagon, if the loop label is to far from the
98/// loop instruction then we need to set the LC0 and SA0 registers
99/// explicitly instead of using LOOP(start,count). This function
100/// checks the distance, and generates register assignments if needed.
101///
102/// This function makes two passes over the basic blocks. The first
103/// pass computes the offset of the basic block from the start.
104/// The second pass checks all the loop instructions.
105bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
106
107 // Offset of the current instruction from the start.
108 unsigned InstOffset = 0;
109 // Map for each basic block to it's first instruction.
111
112 const HexagonInstrInfo *HII =
113 static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo());
114
115 // First pass - compute the offset of each basic block.
116 for (const MachineBasicBlock &MBB : MF) {
117 if (MBB.getAlignment() != Align(1)) {
118 // Although we don't know the exact layout of the final code, we need
119 // to account for alignment padding somehow. This heuristic pads each
120 // aligned basic block according to the alignment value.
121 InstOffset = alignTo(InstOffset, MBB.getAlignment());
122 }
123
124 BlockToInstOffset[&MBB] = InstOffset;
125 for (const MachineInstr &MI : MBB)
126 InstOffset += HII->getSize(MI);
127 }
128
129 // Second pass - check each loop instruction to see if it needs to be
130 // converted.
131 bool Changed = false;
132 for (MachineBasicBlock &MBB : MF) {
133 InstOffset = BlockToInstOffset[&MBB];
134
135 // Loop over all the instructions.
138 while (MII != MIE) {
139 unsigned InstSize = HII->getSize(*MII);
140 if (MII->isMetaInstruction()) {
141 ++MII;
142 continue;
143 }
144 if (isHardwareLoop(*MII)) {
145 assert(MII->getOperand(0).isMBB() &&
146 "Expect a basic block as loop operand");
147 MachineBasicBlock *TargetBB = MII->getOperand(0).getMBB();
148 unsigned Diff = AbsoluteDifference(InstOffset,
149 BlockToInstOffset[TargetBB]);
150 if (Diff > MaxLoopRange) {
151 useExtLoopInstr(MF, MII);
152 MII = MBB.erase(MII);
153 Changed = true;
154 } else {
155 ++MII;
156 }
157 } else {
158 ++MII;
159 }
160 InstOffset += InstSize;
161 }
162 }
163
164 return Changed;
165}
166
167/// Replace loop instructions with the constant extended version.
168void HexagonFixupHwLoops::useExtLoopInstr(MachineFunction &MF,
171 MachineBasicBlock *MBB = MII->getParent();
172 DebugLoc DL = MII->getDebugLoc();
174 unsigned newOp;
175 switch (MII->getOpcode()) {
176 case Hexagon::J2_loop0r:
177 newOp = Hexagon::J2_loop0rext;
178 break;
179 case Hexagon::J2_loop0i:
180 newOp = Hexagon::J2_loop0iext;
181 break;
182 case Hexagon::J2_loop1r:
183 newOp = Hexagon::J2_loop1rext;
184 break;
185 case Hexagon::J2_loop1i:
186 newOp = Hexagon::J2_loop1iext;
187 break;
188 default:
189 llvm_unreachable("Invalid Hardware Loop Instruction.");
190 }
191 MIB = BuildMI(*MBB, MII, DL, TII->get(newOp));
192
193 for (unsigned i = 0; i < MII->getNumOperands(); ++i)
194 MIB.add(MII->getOperand(i));
195}
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file defines the DenseMap class.
const HexagonInstrInfo * TII
static cl::opt< unsigned > MaxLoopRange("hexagon-loop-range", cl::Hidden, cl::init(200), cl::desc("Restrict range of loopN instructions (testing only)"))
static bool isHardwareLoop(const MachineInstr &MI)
Returns true if the instruction is a hardware loop instruction.
IRTranslator LLVM IR MI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Represent the analysis usage information of a pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:269
A debug info location.
Definition: DebugLoc.h:33
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
unsigned getSize(const MachineInstr &MI) const
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
Align getAlignment() const
Return alignment of the basic block.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
Definition: MachineInstr.h:69
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:37
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
TargetInstrInfo - Interface to description of machine instruction set.
virtual const TargetInstrInfo * getInstrInfo() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:450
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createHexagonFixupHwLoops()
std::enable_if_t< std::is_unsigned_v< T >, T > 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:516
void initializeHexagonFixupHwLoopsPass(PassRegistry &)
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39