LLVM 24.0.0git
LeonPasses.cpp
Go to the documentation of this file.
1//===------ LeonPasses.cpp - Define passes specific to LEON ---------------===//
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//===----------------------------------------------------------------------===//
8//
9//
10//===----------------------------------------------------------------------===//
11
12#include "LeonPasses.h"
13#include "Sparc.h"
14#include "SparcSubtarget.h"
23#include "llvm/IR/Analysis.h"
24
25using namespace llvm;
26
28
33
35 "Errata workaround pass", false, false)
36
37// Move iterator to the next instruction in the function, ignoring
38// meta instructions and inline assembly. Returns false when reaching
39// the end of the function.
40static bool moveNext(MachineBasicBlock::iterator &I) {
41
42 MachineBasicBlock *MBB = I->getParent();
43
44 do {
45 I++;
46
47 while (I == MBB->end()) {
48 if (MBB->getFallThrough() == nullptr)
49 return false;
50 MBB = MBB->getFallThrough();
51 I = MBB->begin();
52 }
53 } while (I->isMetaInstruction() || I->isInlineAsm());
54
55 return true;
56}
57
59 const TargetInstrInfo *TII) {
60 BuildMI(*I->getParent(), I, I->getDebugLoc(), TII->get(SP::NOP));
61}
62
64 if (I->getNumOperands() == 0)
65 return false;
66
67 if (!I->getOperand(0).isReg())
68 return false;
69
70 unsigned reg = I->getOperand(0).getReg();
71
72 if (!SP::FPRegsRegClass.contains(reg) && !SP::DFPRegsRegClass.contains(reg))
73 return false;
74
75 return true;
76}
77
79 switch (I->getOpcode()) {
80 case SP::FDIVS:
81 case SP::FDIVD:
82 case SP::FSQRTS:
83 case SP::FSQRTD:
84 return true;
85 }
86 return false;
87}
88
90 switch (I->getOpcode()) {
91 case SP::SWAPrr:
92 case SP::SWAPri:
93 case SP::CASArr:
94 case SP::LDSTUBrr:
95 case SP::LDSTUBri:
96 case SP::LDSTUBArr:
97 return true;
98 }
99 return false;
100}
101
102// Prevents the following code sequence from being generated:
103// (stb/sth/st/stf) -> (single non-store/load instruction) -> (any store)
104// If the sequence is detected a NOP instruction is inserted after
105// the first store instruction.
107 const TargetInstrInfo *TII) {
108 switch (I->getOpcode()) {
109 case SP::STrr:
110 case SP::STri:
111 case SP::STBrr:
112 case SP::STBri:
113 case SP::STHrr:
114 case SP::STHri:
115 case SP::STFrr:
116 case SP::STFri:
117 break;
118 default:
119 return false;
120 }
121
123 if (!moveNext(MI))
124 return false;
125
126 if (MI->mayStore() || MI->mayLoad())
127 return false;
128
130
131 if (!moveNext(MI))
132 return false;
133
134 if (!MI->mayStore())
135 return false;
136
137 insertNop(PatchHere, TII);
138 return true;
139}
140
141// Prevents the following code sequence from being generated:
142// (std/stdf) -> (any store)
143// If the sequence is detected a NOP instruction is inserted after
144// the first store instruction.
146 const TargetInstrInfo *TII) {
147
148 switch (I->getOpcode()) {
149 case SP::STDrr:
150 case SP::STDri:
151 case SP::STDFrr:
152 case SP::STDFri:
153 break;
154 default:
155 return false;
156 }
157
159
160 if (!moveNext(MI))
161 return false;
162
163 if (!MI->mayStore())
164 return false;
165
166 insertNop(MI, TII);
167 return true;
168}
169
170// Insert a NOP at branch target if load in delay slot and atomic
171// instruction at branch target. Also insert a NOP between load
172// instruction and atomic instruction (swap or casa).
174 const TargetInstrInfo *TII) {
175
176 // Check for load instruction or branch bundled with load instruction
177 if (!I->mayLoad())
178 return false;
179
180 // Check for branch to atomic instruction with load in delay slot
181 if (I->isBranch() && I->getOperand(0).isMBB()) {
182 MachineBasicBlock *TargetMBB = I->getOperand(0).getMBB();
183 MachineBasicBlock::iterator MI = TargetMBB->begin();
184
185 while (MI != TargetMBB->end() && MI->isMetaInstruction())
186 MI++;
187
188 if (MI == TargetMBB->end())
189 return false;
190
191 if (isAtomic(MI))
192 insertNop(MI, TII);
193 }
194
195 // Check for load followed by atomic instruction
197 if (!moveNext(MI))
198 return false;
199
200 if (!isAtomic(MI))
201 return false;
202 insertNop(MI, TII);
203 return true;
204}
205
206// Do not allow functions to begin with an atomic instruction
208 const TargetInstrInfo *TII) {
210 while (I != MBB.end() && I->isMetaInstruction())
211 I++;
212 if (I == MBB.end())
213 return false;
214 if (!isAtomic(I))
215 return false;
216 insertNop(I, TII);
217 return true;
218}
219
220// Inserts a NOP instruction at the target of an integer branch if the
221// target is a floating-point instruction or floating-point branch.
223 const TargetInstrInfo *TII) {
224
225 if (I->getOpcode() != SP::BCOND && I->getOpcode() != SP::BCONDA)
226 return false;
227
228 MachineBasicBlock *TargetMBB = I->getOperand(0).getMBB();
229 MachineBasicBlock::iterator MI = TargetMBB->begin();
230
231 while (MI != TargetMBB->end() && MI->isMetaInstruction())
232 MI++;
233
234 if (MI == TargetMBB->end())
235 return false;
236
237 if (!isFloat(MI) && MI->getOpcode() != SP::FBCOND)
238 return false;
239
240 insertNop(MI, TII);
241 return true;
242}
243
244// Prevents the following code sequence from being generated:
245// (div/sqrt) -> (2 to 3 floating-point operations or loads) -> (div/sqrt)
246// If the sequence is detected one or two NOP instruction are inserted after
247// the first div/sqrt instruction. No NOPs are inserted if one of the floating-
248// point instructions in the middle of the sequence is a (div/sqrt), or if
249// they have dependency on the destination register of the first (div/sqrt).
250//
251// The function also prevents the following code sequence from being generated,
252// (div/sqrt) -> (branch), by inserting a NOP instruction after the (div/sqrt).
254 const TargetInstrInfo *TII,
255 const TargetRegisterInfo *TRI) {
256
257 if (!isDivSqrt(I))
258 return false;
259
260 unsigned dstReg = I->getOperand(0).getReg();
261
263 if (!moveNext(MI))
264 return false;
265
266 if (MI->isBranch()) {
267 insertNop(MI, TII);
268 return true;
269 }
270
272
273 unsigned fpFound = 0;
274 for (unsigned i = 0; i < 4; i++) {
275
276 if (!isFloat(MI)) {
277 if (!moveNext(MI))
278 return false;
279 continue;
280 }
281
282 if (MI->readsRegister(dstReg, TRI))
283 return false;
284
285 if (isDivSqrt(MI)) {
286 if (i < 2)
287 return false;
288 if (fpFound < 2)
289 return false;
290
291 insertNop(PatchHere, TII);
292 if (i == 2)
293 insertNop(PatchHere, TII);
294 return true;
295 }
296
297 fpFound++;
298 if (!moveNext(MI))
299 return false;
300 }
301
302 return false;
303}
304
305// On the AT697E and AT697F, a single-word load into an odd-numbered FP register
306// followed by a double-precision operation on the enclosing register pair can
307// give a wrong result (AT697E erratum 13, AT697F erratum 1). On the UT699, a
308// single-cycle load followed by another load or store can fail.
309//
310// Inserts a NOP after any LD or LDF instruction.
312 bool Modified = false;
313 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
314 unsigned Opcode = MBBI->getOpcode();
315 if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) {
316 BuildMI(MBB, std::next(MBBI), DebugLoc(), TII->get(SP::NOP));
317 Modified = true;
318 }
319 }
320 return Modified;
321}
322
324 bool Changed = false;
325 const SparcSubtarget *ST = &MF.getSubtarget<SparcSubtarget>();
326
327 if (!(ST->insertNOPLoad() || ST->fixTN0009() || ST->fixTN0010() ||
328 ST->fixTN0012() || ST->fixTN0013()))
329 return false;
330
331 const TargetInstrInfo *TII = ST->getInstrInfo();
332 const TargetRegisterInfo *TRI = ST->getRegisterInfo();
333
334 if (ST->insertNOPLoad())
335 for (auto &MBB : MF)
337
338 if (ST->fixTN0010())
340
341 for (auto &MBB : MF) {
342 for (auto &I : MBB) {
343 if (ST->fixTN0009()) {
346 }
347 if (ST->fixTN0010())
349 if (ST->fixTN0012())
351 if (ST->fixTN0013())
353 }
354 }
355 return Changed;
356}
357
361
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
static bool isDivSqrt(MachineBasicBlock::iterator I)
static bool isFloat(MachineBasicBlock::iterator I)
static bool checkSeqTN0010First(MachineBasicBlock &MBB, const TargetInstrInfo *TII)
static bool checkSeqTN0010(MachineBasicBlock::iterator I, const TargetInstrInfo *TII)
static bool insertNOPLoad(MachineBasicBlock &MBB, const TargetInstrInfo *TII)
static bool isAtomic(MachineBasicBlock::iterator I)
static bool runErrataWorkaroundOnMachineFunction(MachineFunction &MF)
static bool checkSeqTN0009A(MachineBasicBlock::iterator I, const TargetInstrInfo *TII)
static bool checkSeqTN0013(MachineBasicBlock::iterator I, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
static void insertNop(MachineBasicBlock::iterator I, const TargetInstrInfo *TII)
static bool checkSeqTN0012(MachineBasicBlock::iterator I, const TargetInstrInfo *TII)
static bool checkSeqTN0009B(MachineBasicBlock::iterator I, const TargetInstrInfo *TII)
#define I(x, y, z)
Definition MD5.cpp:57
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:479
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
MachineInstrBundleIterator< MachineInstr > iterator
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const MachineBasicBlock & front() const
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Pass manager infrastructure for declaring and invalidating analyses.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
void initializeSparcErrataWorkaroundLegacyPass(PassRegistry &)