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"
25
26using namespace llvm;
27
29
34
36 "Errata workaround pass", false, false)
37
38// Move iterator to the next instruction in the function, ignoring
39// meta instructions and inline assembly. Returns false when reaching
40// the end of the function.
41static bool moveNext(MachineBasicBlock::iterator &I) {
42
43 MachineBasicBlock *MBB = I->getParent();
44
45 do {
46 I++;
47
48 while (I == MBB->end()) {
49 if (MBB->getFallThrough() == nullptr)
50 return false;
51 MBB = MBB->getFallThrough();
52 I = MBB->begin();
53 }
54 } while (I->isMetaInstruction() || I->isInlineAsm());
55
56 return true;
57}
58
60 const TargetInstrInfo *TII) {
61 BuildMI(*I->getParent(), I, I->getDebugLoc(), TII->get(SP::NOP));
62}
63
65 if (I->getNumOperands() == 0)
66 return false;
67
68 if (!I->getOperand(0).isReg())
69 return false;
70
71 unsigned reg = I->getOperand(0).getReg();
72
73 if (!SP::FPRegsRegClass.contains(reg) && !SP::DFPRegsRegClass.contains(reg))
74 return false;
75
76 return true;
77}
78
80 switch (I->getOpcode()) {
81 case SP::FDIVS:
82 case SP::FDIVD:
83 case SP::FSQRTS:
84 case SP::FSQRTD:
85 return true;
86 }
87 return false;
88}
89
91 switch (I->getOpcode()) {
92 case SP::SWAPrr:
93 case SP::SWAPri:
94 case SP::CASArr:
95 case SP::LDSTUBrr:
96 case SP::LDSTUBri:
97 case SP::LDSTUBArr:
98 return true;
99 }
100 return false;
101}
102
103// Prevents the following code sequence from being generated:
104// (stb/sth/st/stf) -> (single non-store/load instruction) -> (any store)
105// If the sequence is detected a NOP instruction is inserted after
106// the first store instruction.
108 const TargetInstrInfo *TII) {
109 switch (I->getOpcode()) {
110 case SP::STrr:
111 case SP::STri:
112 case SP::STBrr:
113 case SP::STBri:
114 case SP::STHrr:
115 case SP::STHri:
116 case SP::STFrr:
117 case SP::STFri:
118 break;
119 default:
120 return false;
121 }
122
124 if (!moveNext(MI))
125 return false;
126
127 if (MI->mayStore() || MI->mayLoad())
128 return false;
129
131
132 if (!moveNext(MI))
133 return false;
134
135 if (!MI->mayStore())
136 return false;
137
138 insertNop(PatchHere, TII);
139 return true;
140}
141
142// Prevents the following code sequence from being generated:
143// (std/stdf) -> (any store)
144// If the sequence is detected a NOP instruction is inserted after
145// the first store instruction.
147 const TargetInstrInfo *TII) {
148
149 switch (I->getOpcode()) {
150 case SP::STDrr:
151 case SP::STDri:
152 case SP::STDFrr:
153 case SP::STDFri:
154 break;
155 default:
156 return false;
157 }
158
160
161 if (!moveNext(MI))
162 return false;
163
164 if (!MI->mayStore())
165 return false;
166
167 insertNop(MI, TII);
168 return true;
169}
170
171// Insert a NOP at branch target if load in delay slot and atomic
172// instruction at branch target. Also insert a NOP between load
173// instruction and atomic instruction (swap or casa).
175 const TargetInstrInfo *TII) {
176
177 // Check for load instruction or branch bundled with load instruction
178 if (!I->mayLoad())
179 return false;
180
181 // Check for branch to atomic instruction with load in delay slot
182 if (I->isBranch() && I->getOperand(0).isMBB()) {
183 MachineBasicBlock *TargetMBB = I->getOperand(0).getMBB();
184 MachineBasicBlock::iterator MI = TargetMBB->begin();
185
186 while (MI != TargetMBB->end() && MI->isMetaInstruction())
187 MI++;
188
189 if (MI == TargetMBB->end())
190 return false;
191
192 if (isAtomic(MI))
193 insertNop(MI, TII);
194 }
195
196 // Check for load followed by atomic instruction
198 if (!moveNext(MI))
199 return false;
200
201 if (!isAtomic(MI))
202 return false;
203 insertNop(MI, TII);
204 return true;
205}
206
207// Do not allow functions to begin with an atomic instruction
209 const TargetInstrInfo *TII) {
211 while (I != MBB.end() && I->isMetaInstruction())
212 I++;
213 if (I == MBB.end())
214 return false;
215 if (!isAtomic(I))
216 return false;
217 insertNop(I, TII);
218 return true;
219}
220
221// Inserts a NOP instruction at the target of an integer branch if the
222// target is a floating-point instruction or floating-point branch.
224 const TargetInstrInfo *TII) {
225
226 if (I->getOpcode() != SP::BCOND && I->getOpcode() != SP::BCONDA)
227 return false;
228
229 MachineBasicBlock *TargetMBB = I->getOperand(0).getMBB();
230 MachineBasicBlock::iterator MI = TargetMBB->begin();
231
232 while (MI != TargetMBB->end() && MI->isMetaInstruction())
233 MI++;
234
235 if (MI == TargetMBB->end())
236 return false;
237
238 if (!isFloat(MI) && MI->getOpcode() != SP::FBCOND)
239 return false;
240
241 insertNop(MI, TII);
242 return true;
243}
244
245// Prevents the following code sequence from being generated:
246// (div/sqrt) -> (2 to 3 floating-point operations or loads) -> (div/sqrt)
247// If the sequence is detected one or two NOP instruction are inserted after
248// the first div/sqrt instruction. No NOPs are inserted if one of the floating-
249// point instructions in the middle of the sequence is a (div/sqrt), or if
250// they have dependency on the destination register of the first (div/sqrt).
251//
252// The function also prevents the following code sequence from being generated,
253// (div/sqrt) -> (branch), by inserting a NOP instruction after the (div/sqrt).
255 const TargetInstrInfo *TII,
256 const TargetRegisterInfo *TRI) {
257
258 if (!isDivSqrt(I))
259 return false;
260
261 unsigned dstReg = I->getOperand(0).getReg();
262
264 if (!moveNext(MI))
265 return false;
266
267 if (MI->isBranch()) {
268 insertNop(MI, TII);
269 return true;
270 }
271
273
274 unsigned fpFound = 0;
275 for (unsigned i = 0; i < 4; i++) {
276
277 if (!isFloat(MI)) {
278 if (!moveNext(MI))
279 return false;
280 continue;
281 }
282
283 if (MI->readsRegister(dstReg, TRI))
284 return false;
285
286 if (isDivSqrt(MI)) {
287 if (i < 2)
288 return false;
289 if (fpFound < 2)
290 return false;
291
292 insertNop(PatchHere, TII);
293 if (i == 2)
294 insertNop(PatchHere, TII);
295 return true;
296 }
297
298 fpFound++;
299 if (!moveNext(MI))
300 return false;
301 }
302
303 return false;
304}
305
307 bool Changed = false;
308 const SparcSubtarget *ST = &MF.getSubtarget<SparcSubtarget>();
309
310 if (!(ST->fixTN0009() || ST->fixTN0010() || ST->fixTN0012() ||
311 ST->fixTN0013()))
312 return false;
313
314 const TargetInstrInfo *TII = ST->getInstrInfo();
315 const TargetRegisterInfo *TRI = ST->getRegisterInfo();
316
317 if (ST->fixTN0010())
319
320 for (auto &MBB : MF) {
321 for (auto &I : MBB) {
322 if (ST->fixTN0009()) {
325 }
326 if (ST->fixTN0010())
328 if (ST->fixTN0012())
330 if (ST->fixTN0013())
332 }
333 }
334 return Changed;
335}
336
340
349
350//*****************************************************************************
351//**** InsertNOPLoad pass
352//*****************************************************************************
353// This pass fixes the incorrectly working Load instructions that exists for
354// some earlier versions of the LEON processor line. NOP instructions must
355// be inserted after the load instruction to ensure that the Load instruction
356// behaves as expected for these processors.
357//
358// This pass inserts a NOP after any LD or LDF instruction.
359//
361
364
366 const SparcSubtarget *Subtarget = &MF.getSubtarget<SparcSubtarget>();
367 if (!Subtarget->insertNOPLoad())
368 return false;
369
370 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
371 DebugLoc DL = DebugLoc();
372
373 bool Modified = false;
374 for (MachineBasicBlock &MBB : MF) {
375 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
376 MachineInstr &MI = *MBBI;
377 unsigned Opcode = MI.getOpcode();
378 if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) {
379 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
380 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
381 Modified = true;
382 }
383 }
384 }
385
386 return Modified;
387}
388
392
401
402//*****************************************************************************
403//**** DetectRoundChange pass
404//*****************************************************************************
405// To prevent any explicit change of the default rounding mode, this pass
406// detects any call of the fesetround function.
407// A warning is generated to ensure the user knows this has happened.
408//
409// Detects an erratum in UT699 LEON 3 processor
410
412
415
417 const SparcSubtarget *Subtarget = &MF.getSubtarget<SparcSubtarget>();
418 if (!Subtarget->detectRoundChange())
419 return false;
420
421 bool Modified = false;
422 for (MachineBasicBlock &MBB : MF) {
423 for (MachineInstr &MI : MBB) {
424 unsigned Opcode = MI.getOpcode();
425 if (Opcode == SP::CALL && MI.getNumOperands() > 0) {
426 MachineOperand &MO = MI.getOperand(0);
427
428 if (MO.isGlobal()) {
429 StringRef FuncName = MO.getGlobal()->getName();
430 if (FuncName.compare_insensitive("fesetround") == 0) {
431 errs() << "Error: You are using the detectroundchange "
432 "option to detect rounding changes that will "
433 "cause LEON errata. The only way to fix this "
434 "is to remove the call to fesetround from "
435 "the source code.\n";
436 }
437 }
438 }
439 }
440 }
441
442 return Modified;
443}
444
448
455
456//*****************************************************************************
457//**** FixAllFDIVSQRT pass
458//*****************************************************************************
459// This pass fixes the incorrectly working FDIVx and FSQRTx instructions that
460// exist for some earlier versions of the LEON processor line. Five NOP
461// instructions need to be inserted after these instructions to ensure the
462// correct result is placed in the destination registers before they are used.
463//
464// This pass implements two fixes:
465// 1) fixing the FSQRTS and FSQRTD instructions.
466// 2) fixing the FDIVS and FDIVD instructions.
467//
468// FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in
469// the pipeline when this option is enabled, so this pass needs only to deal
470// with the changes that still need implementing for the "double" versions
471// of these instructions.
472//
474
477
479 const SparcSubtarget *Subtarget = &MF.getSubtarget<SparcSubtarget>();
480 if (!Subtarget->fixAllFDIVSQRT())
481 return false;
482
483 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
484 DebugLoc DL = DebugLoc();
485
486 bool Modified = false;
487 for (MachineBasicBlock &MBB : MF) {
488 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
489 MachineInstr &MI = *MBBI;
490 unsigned Opcode = MI.getOpcode();
491
492 // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is
493 // switched on so we don't need to check for them here. They will
494 // already have been converted to FSQRTD or FDIVD earlier in the
495 // pipeline.
496 if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) {
497 for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++)
498 BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
499
500 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
501 for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++)
502 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
503
504 Modified = true;
505 }
506 }
507 }
508
509 return Modified;
510}
511
515
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
static bool detectRoundChangeOnMachineFunction(MachineFunction &MF)
static bool isDivSqrt(MachineBasicBlock::iterator I)
static bool fixAllFDIVSQRTInMachineFunction(MachineFunction &MF)
static bool insertNOPLoadInMachineFunction(MachineFunction &MF)
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 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:480
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
A debug info location.
Definition DebugLoc.h:126
MachineInstrBundleIterator< MachineInstr > iterator
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.
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 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)
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
const SparcInstrInfo * getInstrInfo() const override
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
LLVM_ABI int compare_insensitive(StringRef RHS) const
Compare two strings, ignoring case.
Definition StringRef.cpp:32
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:315
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 &)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.