Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonFixupHwLoops.cpp
35267 views
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"
15
#include "HexagonTargetMachine.h"
16
#include "llvm/ADT/DenseMap.h"
17
#include "llvm/CodeGen/MachineFunction.h"
18
#include "llvm/CodeGen/MachineFunctionPass.h"
19
#include "llvm/CodeGen/MachineInstrBuilder.h"
20
#include "llvm/CodeGen/Passes.h"
21
#include "llvm/CodeGen/TargetInstrInfo.h"
22
#include "llvm/Support/MathExtras.h"
23
#include "llvm/Pass.h"
24
25
using namespace llvm;
26
27
static cl::opt<unsigned> MaxLoopRange(
28
"hexagon-loop-range", cl::Hidden, cl::init(200),
29
cl::desc("Restrict range of loopN instructions (testing only)"));
30
31
namespace llvm {
32
FunctionPass *createHexagonFixupHwLoops();
33
void initializeHexagonFixupHwLoopsPass(PassRegistry&);
34
}
35
36
namespace {
37
struct HexagonFixupHwLoops : public MachineFunctionPass {
38
public:
39
static char ID;
40
41
HexagonFixupHwLoops() : MachineFunctionPass(ID) {
42
initializeHexagonFixupHwLoopsPass(*PassRegistry::getPassRegistry());
43
}
44
45
bool runOnMachineFunction(MachineFunction &MF) override;
46
47
MachineFunctionProperties getRequiredProperties() const override {
48
return MachineFunctionProperties().set(
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();
58
MachineFunctionPass::getAnalysisUsage(AU);
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,
70
MachineBasicBlock::iterator &MII);
71
};
72
73
char HexagonFixupHwLoops::ID = 0;
74
}
75
76
INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",
77
"Hexagon Hardware Loops Fixup", false, false)
78
79
FunctionPass *llvm::createHexagonFixupHwLoops() {
80
return new HexagonFixupHwLoops();
81
}
82
83
/// Returns true if the instruction is a hardware loop instruction.
84
static 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
91
bool 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.
105
bool 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.
110
DenseMap<const MachineBasicBlock *, unsigned> BlockToInstOffset;
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.
136
MachineBasicBlock::iterator MII = MBB.begin();
137
MachineBasicBlock::iterator MIE = MBB.end();
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.
168
void HexagonFixupHwLoops::useExtLoopInstr(MachineFunction &MF,
169
MachineBasicBlock::iterator &MII) {
170
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
171
MachineBasicBlock *MBB = MII->getParent();
172
DebugLoc DL = MII->getDebugLoc();
173
MachineInstrBuilder MIB;
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
}
196
197