LLVM 20.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 "SparcSubtarget.h"
19
20using namespace llvm;
21
23
26}
27
28INITIALIZE_PASS(ErrataWorkaround, "errata-workaround", "Errata workaround pass",
29 false, false)
30
31// Move iterator to the next instruction in the function, ignoring
32// meta instructions and inline assembly. Returns false when reaching
33// the end of the function.
34bool ErrataWorkaround::moveNext(MachineBasicBlock::iterator &I) {
35
36 MachineBasicBlock *MBB = I->getParent();
37
38 do {
39 I++;
40
41 while (I == MBB->end()) {
42 if (MBB->getFallThrough() == nullptr)
43 return false;
45 I = MBB->begin();
46 }
47 } while (I->isMetaInstruction() || I->isInlineAsm());
48
49 return true;
50}
51
53 BuildMI(*I->getParent(), I, I->getDebugLoc(), TII->get(SP::NOP));
54}
55
57 if (I->getNumOperands() == 0)
58 return false;
59
60 if (!I->getOperand(0).isReg())
61 return false;
62
63 unsigned reg = I->getOperand(0).getReg();
64
65 if (!SP::FPRegsRegClass.contains(reg) && !SP::DFPRegsRegClass.contains(reg))
66 return false;
67
68 return true;
69}
70
72 switch (I->getOpcode()) {
73 case SP::FDIVS:
74 case SP::FDIVD:
75 case SP::FSQRTS:
76 case SP::FSQRTD:
77 return true;
78 }
79 return false;
80}
81
82// Prevents the following code sequence from being generated:
83// (stb/sth/st/stf) -> (single non-store/load instruction) -> (any store)
84// If the sequence is detected a NOP instruction is inserted after
85// the first store instruction.
87 switch (I->getOpcode()) {
88 case SP::STrr:
89 case SP::STri:
90 case SP::STBrr:
91 case SP::STBri:
92 case SP::STHrr:
93 case SP::STHri:
94 case SP::STFrr:
95 case SP::STFri:
96 break;
97 default:
98 return false;
99 }
100
102 if (!moveNext(MI))
103 return false;
104
105 if (MI->mayStore() || MI->mayLoad())
106 return false;
107
109
110 if (!moveNext(MI))
111 return false;
112
113 if (!MI->mayStore())
114 return false;
115
116 insertNop(PatchHere);
117 return true;
118}
119
120// Prevents the following code sequence from being generated:
121// (std/stdf) -> (any store)
122// If the sequence is detected a NOP instruction is inserted after
123// the first store instruction.
125
126 switch (I->getOpcode()) {
127 case SP::STDrr:
128 case SP::STDri:
129 case SP::STDFrr:
130 case SP::STDFri:
131 break;
132 default:
133 return false;
134 }
135
137
138 if (!moveNext(MI))
139 return false;
140
141 if (!MI->mayStore())
142 return false;
143
144 insertNop(MI);
145 return true;
146}
147
148// Insert a NOP at branch target if load in delay slot and atomic
149// instruction at branch target. Also insert a NOP between load
150// instruction and atomic instruction (swap or casa).
152
153 // Check for load instruction or branch bundled with load instruction
154 if (!I->mayLoad())
155 return false;
156
157 // Check for branch to atomic instruction with load in delay slot
158 if (I->isBranch()) {
159 MachineBasicBlock *TargetMBB = I->getOperand(0).getMBB();
160 MachineBasicBlock::iterator MI = TargetMBB->begin();
161
162 while (MI != TargetMBB->end() && MI->isMetaInstruction())
163 MI++;
164
165 if (MI == TargetMBB->end())
166 return false;
167
168 switch (MI->getOpcode()) {
169 case SP::SWAPrr:
170 case SP::SWAPri:
171 case SP::CASArr:
172 insertNop(MI);
173 break;
174 default:
175 break;
176 }
177 }
178
179 // Check for load followed by atomic instruction
181 if (!moveNext(MI))
182 return false;
183
184 switch (MI->getOpcode()) {
185 case SP::SWAPrr:
186 case SP::SWAPri:
187 case SP::CASArr:
188 break;
189 default:
190 return false;
191 }
192 insertNop(MI);
193 return true;
194}
195
196// Do not allow functions to begin with an atomic instruction
199 while (I != MBB.end() && I->isMetaInstruction())
200 I++;
201 switch (I->getOpcode()) {
202 case SP::SWAPrr:
203 case SP::SWAPri:
204 case SP::CASArr:
205 break;
206 default:
207 return false;
208 }
209 insertNop(I);
210 return true;
211}
212
213// Inserts a NOP instruction at the target of an integer branch if the
214// target is a floating-point instruction or floating-point branch.
216
217 if (I->getOpcode() != SP::BCOND && I->getOpcode() != SP::BCONDA)
218 return false;
219
220 MachineBasicBlock *TargetMBB = I->getOperand(0).getMBB();
221 MachineBasicBlock::iterator MI = TargetMBB->begin();
222
223 while (MI != TargetMBB->end() && MI->isMetaInstruction())
224 MI++;
225
226 if (MI == TargetMBB->end())
227 return false;
228
229 if (!isFloat(MI) && MI->getOpcode() != SP::FBCOND)
230 return false;
231
232 insertNop(MI);
233 return true;
234}
235
236// Prevents the following code sequence from being generated:
237// (div/sqrt) -> (2 to 3 floating-point operations or loads) -> (div/sqrt)
238// If the sequence is detected one or two NOP instruction are inserted after
239// the first div/sqrt instruction. No NOPs are inserted if one of the floating-
240// point instructions in the middle of the sequence is a (div/sqrt), or if
241// they have dependency on the destination register of the first (div/sqrt).
242//
243// The function also prevents the following code sequence from being generated,
244// (div/sqrt) -> (branch), by inserting a NOP instruction after the (div/sqrt).
246
247 if (!isDivSqrt(I))
248 return false;
249
250 unsigned dstReg = I->getOperand(0).getReg();
251
253 if (!moveNext(MI))
254 return false;
255
256 if (MI->isBranch()) {
257 insertNop(MI);
258 return true;
259 }
260
262
263 unsigned fpFound = 0;
264 for (unsigned i = 0; i < 4; i++) {
265
266 if (!isFloat(MI)) {
267 if (!moveNext(MI))
268 return false;
269 continue;
270 }
271
272 if (MI->readsRegister(dstReg, TRI))
273 return false;
274
275 if (isDivSqrt(MI)) {
276 if (i < 2)
277 return false;
278 if (fpFound < 2)
279 return false;
280
281 insertNop(PatchHere);
282 if (i == 2)
283 insertNop(PatchHere);
284 return true;
285 }
286
287 fpFound++;
288 if (!moveNext(MI))
289 return false;
290 }
291
292 return false;
293}
294
296 bool Changed = false;
298
299 if (!(ST->fixTN0009() || ST->fixTN0010() || ST->fixTN0012() ||
300 ST->fixTN0013()))
301 return false;
302
303 TII = ST->getInstrInfo();
305
306 if (ST->fixTN0010())
307 Changed |= checkSeqTN0010First(MF.front());
308
309 for (auto &MBB : MF) {
310 for (auto &I : MBB) {
311 if (ST->fixTN0009()) {
312 Changed |= checkSeqTN0009A(I);
313 Changed |= checkSeqTN0009B(I);
314 }
315 if (ST->fixTN0010())
316 Changed |= checkSeqTN0010(I);
317 if (ST->fixTN0012())
318 Changed |= checkSeqTN0012(I);
319 if (ST->fixTN0013())
320 Changed |= checkSeqTN0013(I);
321 }
322 }
323 return Changed;
324}
325
328
329//*****************************************************************************
330//**** InsertNOPLoad pass
331//*****************************************************************************
332// This pass fixes the incorrectly working Load instructions that exists for
333// some earlier versions of the LEON processor line. NOP instructions must
334// be inserted after the load instruction to ensure that the Load instruction
335// behaves as expected for these processors.
336//
337// This pass inserts a NOP after any LD or LDF instruction.
338//
339char InsertNOPLoad::ID = 0;
340
342
345 if (!Subtarget->insertNOPLoad())
346 return false;
347
349 DebugLoc DL = DebugLoc();
350
351 bool Modified = false;
352 for (MachineBasicBlock &MBB : MF) {
353 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
354 MachineInstr &MI = *MBBI;
355 unsigned Opcode = MI.getOpcode();
356 if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) {
357 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
358 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
359 Modified = true;
360 }
361 }
362 }
363
364 return Modified;
365}
366
367
368
369//*****************************************************************************
370//**** DetectRoundChange pass
371//*****************************************************************************
372// To prevent any explicit change of the default rounding mode, this pass
373// detects any call of the fesetround function.
374// A warning is generated to ensure the user knows this has happened.
375//
376// Detects an erratum in UT699 LEON 3 processor
377
378char DetectRoundChange::ID = 0;
379
381
384 if (!Subtarget->detectRoundChange())
385 return false;
386
387 bool Modified = false;
388 for (MachineBasicBlock &MBB : MF) {
389 for (MachineInstr &MI : MBB) {
390 unsigned Opcode = MI.getOpcode();
391 if (Opcode == SP::CALL && MI.getNumOperands() > 0) {
392 MachineOperand &MO = MI.getOperand(0);
393
394 if (MO.isGlobal()) {
395 StringRef FuncName = MO.getGlobal()->getName();
396 if (FuncName.compare_insensitive("fesetround") == 0) {
397 errs() << "Error: You are using the detectroundchange "
398 "option to detect rounding changes that will "
399 "cause LEON errata. The only way to fix this "
400 "is to remove the call to fesetround from "
401 "the source code.\n";
402 }
403 }
404 }
405 }
406 }
407
408 return Modified;
409}
410
411//*****************************************************************************
412//**** FixAllFDIVSQRT pass
413//*****************************************************************************
414// This pass fixes the incorrectly working FDIVx and FSQRTx instructions that
415// exist for some earlier versions of the LEON processor line. Five NOP
416// instructions need to be inserted after these instructions to ensure the
417// correct result is placed in the destination registers before they are used.
418//
419// This pass implements two fixes:
420// 1) fixing the FSQRTS and FSQRTD instructions.
421// 2) fixing the FDIVS and FDIVD instructions.
422//
423// FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in
424// the pipeline when this option is enabled, so this pass needs only to deal
425// with the changes that still need implementing for the "double" versions
426// of these instructions.
427//
428char FixAllFDIVSQRT::ID = 0;
429
431
434 if (!Subtarget->fixAllFDIVSQRT())
435 return false;
436
438 DebugLoc DL = DebugLoc();
439
440 bool Modified = false;
441 for (MachineBasicBlock &MBB : MF) {
442 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
443 MachineInstr &MI = *MBBI;
444 unsigned Opcode = MI.getOpcode();
445
446 // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is
447 // switched on so we don't need to check for them here. They will
448 // already have been converted to FSQRTD or FDIVD earlier in the
449 // pipeline.
450 if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) {
451 for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++)
452 BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
453
454 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
455 for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++)
456 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
457
458 Modified = true;
459 }
460 }
461 }
462
463 return Modified;
464}
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
A debug info location.
Definition: DebugLoc.h:33
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition: LeonPasses.cpp:382
bool checkSeqTN0009A(MachineBasicBlock::iterator I)
Definition: LeonPasses.cpp:86
bool checkSeqTN0013(MachineBasicBlock::iterator I)
Definition: LeonPasses.cpp:245
bool checkSeqTN0010First(MachineBasicBlock &MBB)
Definition: LeonPasses.cpp:197
bool moveNext(MachineBasicBlock::iterator &I)
const SparcSubtarget * ST
Definition: LeonPasses.h:42
bool checkSeqTN0012(MachineBasicBlock::iterator I)
Definition: LeonPasses.cpp:215
bool checkSeqTN0010(MachineBasicBlock::iterator I)
Definition: LeonPasses.cpp:151
bool checkSeqTN0009B(MachineBasicBlock::iterator I)
Definition: LeonPasses.cpp:124
const TargetInstrInfo * TII
Definition: LeonPasses.h:43
bool isDivSqrt(MachineBasicBlock::iterator I)
Definition: LeonPasses.cpp:71
bool isFloat(MachineBasicBlock::iterator I)
Definition: LeonPasses.cpp:56
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition: LeonPasses.cpp:295
const TargetRegisterInfo * TRI
Definition: LeonPasses.h:44
void insertNop(MachineBasicBlock::iterator I)
Definition: LeonPasses.cpp:52
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition: LeonPasses.cpp:432
static char ID
Definition: LeonPasses.h:97
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition: LeonPasses.cpp:343
static char ID
Definition: LeonPasses.h:69
const SparcSubtarget * Subtarget
Definition: LeonPasses.h:23
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:63
MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const MachineBasicBlock & front() const
Representation of each machine instruction.
Definition: MachineInstr.h:69
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
const SparcRegisterInfo * getRegisterInfo() const override
const SparcInstrInfo * getInstrInfo() const override
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
int compare_insensitive(StringRef RHS) const
Compare two strings, ignoring case.
Definition: StringRef.cpp:37
TargetInstrInfo - Interface to description of machine instruction set.
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
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.
void initializeErrataWorkaroundPass(PassRegistry &)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.