LLVM  4.0.0
LeonPasses.cpp
Go to the documentation of this file.
1 //===------ LeonPasses.cpp - Define passes specific to LEON ---------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "LeonPasses.h"
19 #include "llvm/IR/DiagnosticInfo.h"
20 #include "llvm/IR/LLVMContext.h"
22 using namespace llvm;
23 
25  : MachineFunctionPass(ID) {}
26 
28  : MachineFunctionPass(ID) {}
29 
31  int OperandIndex) {
32  if (MI.getNumOperands() > 0) {
33  if (OperandIndex == LAST_OPERAND) {
34  OperandIndex = MI.getNumOperands() - 1;
35  }
36 
37  if (MI.getNumOperands() > (unsigned)OperandIndex &&
38  MI.getOperand(OperandIndex).isReg()) {
39  return (int)MI.getOperand(OperandIndex).getReg();
40  }
41  }
42 
43  static int NotFoundIndex = -10;
44  // Return a different number each time to avoid any comparisons between the
45  // values returned.
46  NotFoundIndex -= 10;
47  return NotFoundIndex;
48 }
49 
50 // finds a new free FP register
51 // checks also the AllocatedRegisters vector
53  for (int RegisterIndex = SP::F0; RegisterIndex <= SP::F31; ++RegisterIndex) {
54  if (!MRI.isPhysRegUsed(RegisterIndex) &&
55  !is_contained(UsedRegisters, RegisterIndex)) {
56  return RegisterIndex;
57  }
58  }
59 
60  return -1;
61 }
62 
63 //*****************************************************************************
64 //**** InsertNOPLoad pass
65 //*****************************************************************************
66 // This pass fixes the incorrectly working Load instructions that exists for
67 // some earlier versions of the LEON processor line. NOP instructions must
68 // be inserted after the load instruction to ensure that the Load instruction
69 // behaves as expected for these processors.
70 //
71 // This pass inserts a NOP after any LD or LDF instruction.
72 //
73 char InsertNOPLoad::ID = 0;
74 
76  : LEONMachineFunctionPass(tm, ID) {}
77 
81  DebugLoc DL = DebugLoc();
82 
83  bool Modified = false;
84  for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
85  MachineBasicBlock &MBB = *MFI;
86  for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
87  MachineInstr &MI = *MBBI;
88  unsigned Opcode = MI.getOpcode();
89  if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) {
90  MachineBasicBlock::iterator NMBBI = std::next(MBBI);
91  BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
92  Modified = true;
93  }
94  }
95  }
96 
97  return Modified;
98 }
99 
100 //*****************************************************************************
101 //**** FixFSMULD pass
102 //*****************************************************************************
103 // This pass fixes the incorrectly working FSMULD instruction that exists for
104 // some earlier versions of the LEON processor line.
105 //
106 // The pass should convert the FSMULD operands to double precision in scratch
107 // registers, then calculate the result with the FMULD instruction. Therefore,
108 // the pass should replace operations of the form:
109 // fsmuld %f20,%f21,%f8
110 // with the sequence:
111 // fstod %f20,%f0
112 // fstod %f21,%f2
113 // fmuld %f0,%f2,%f8
114 //
115 char FixFSMULD::ID = 0;
116 
118 
122  DebugLoc DL = DebugLoc();
123 
124  bool Modified = false;
125  for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
126  MachineBasicBlock &MBB = *MFI;
127  for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
128 
129  MachineInstr &MI = *MBBI;
130  unsigned Opcode = MI.getOpcode();
131 
132  const int UNASSIGNED_INDEX = -1;
133  int Reg1Index = UNASSIGNED_INDEX;
134  int Reg2Index = UNASSIGNED_INDEX;
135  int Reg3Index = UNASSIGNED_INDEX;
136 
137  if (Opcode == SP::FSMULD && MI.getNumOperands() == 3) {
138  // take the registers from fsmuld %f20,%f21,%f8
139  Reg1Index = MI.getOperand(0).getReg();
140  Reg2Index = MI.getOperand(1).getReg();
141  Reg3Index = MI.getOperand(2).getReg();
142  }
143 
144  if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
145  Reg3Index != UNASSIGNED_INDEX) {
147  MachineBasicBlock::iterator NMBBI = std::next(MBBI);
148  // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
149  markRegisterUsed(Reg3Index);
150  const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
151  markRegisterUsed(ScratchReg1Index);
152  const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
153  markRegisterUsed(ScratchReg2Index);
154 
155  if (ScratchReg1Index == UNASSIGNED_INDEX ||
156  ScratchReg2Index == UNASSIGNED_INDEX) {
157  errs() << "Cannot allocate free scratch registers for the FixFSMULD "
158  "pass."
159  << "\n";
160  } else {
161  // create fstod %f20,%f0
162  BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
163  .addReg(ScratchReg1Index)
164  .addReg(Reg1Index);
165 
166  // create fstod %f21,%f2
167  BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
168  .addReg(ScratchReg2Index)
169  .addReg(Reg2Index);
170 
171  // create fmuld %f0,%f2,%f8
172  BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
173  .addReg(Reg3Index)
174  .addReg(ScratchReg1Index)
175  .addReg(ScratchReg2Index);
176 
177  MI.eraseFromParent();
178  MBBI = NMBBI;
179 
180  Modified = true;
181  }
182  }
183  }
184  }
185 
186  return Modified;
187 }
188 
189 //*****************************************************************************
190 //**** ReplaceFMULS pass
191 //*****************************************************************************
192 // This pass fixes the incorrectly working FMULS instruction that exists for
193 // some earlier versions of the LEON processor line.
194 //
195 // This pass converts the FMULS operands to double precision in scratch
196 // registers, then calculates the result with the FMULD instruction.
197 // The pass should replace operations of the form:
198 // fmuls %f20,%f21,%f8
199 // with the sequence:
200 // fstod %f20,%f0
201 // fstod %f21,%f2
202 // fmuld %f0,%f2,%f8
203 //
204 char ReplaceFMULS::ID = 0;
205 
207  : LEONMachineFunctionPass(tm, ID) {}
208 
212  DebugLoc DL = DebugLoc();
213 
214  bool Modified = false;
215  for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
216  MachineBasicBlock &MBB = *MFI;
217  for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
218  MachineInstr &MI = *MBBI;
219  unsigned Opcode = MI.getOpcode();
220 
221  const int UNASSIGNED_INDEX = -1;
222  int Reg1Index = UNASSIGNED_INDEX;
223  int Reg2Index = UNASSIGNED_INDEX;
224  int Reg3Index = UNASSIGNED_INDEX;
225 
226  if (Opcode == SP::FMULS && MI.getNumOperands() == 3) {
227  // take the registers from fmuls %f20,%f21,%f8
228  Reg1Index = MI.getOperand(0).getReg();
229  Reg2Index = MI.getOperand(1).getReg();
230  Reg3Index = MI.getOperand(2).getReg();
231  }
232 
233  if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
234  Reg3Index != UNASSIGNED_INDEX) {
236  MachineBasicBlock::iterator NMBBI = std::next(MBBI);
237  // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
238  markRegisterUsed(Reg3Index);
239  const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
240  markRegisterUsed(ScratchReg1Index);
241  const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
242  markRegisterUsed(ScratchReg2Index);
243 
244  if (ScratchReg1Index == UNASSIGNED_INDEX ||
245  ScratchReg2Index == UNASSIGNED_INDEX) {
246  errs() << "Cannot allocate free scratch registers for the "
247  "ReplaceFMULS pass."
248  << "\n";
249  } else {
250  // create fstod %f20,%f0
251  BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
252  .addReg(ScratchReg1Index)
253  .addReg(Reg1Index);
254 
255  // create fstod %f21,%f2
256  BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
257  .addReg(ScratchReg2Index)
258  .addReg(Reg2Index);
259 
260  // create fmuld %f0,%f2,%f8
261  BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
262  .addReg(Reg3Index)
263  .addReg(ScratchReg1Index)
264  .addReg(ScratchReg2Index);
265 
266  MI.eraseFromParent();
267  MBBI = NMBBI;
268 
269  Modified = true;
270  }
271  }
272  }
273  }
274 
275  return Modified;
276 }
277 
278 
279 //*****************************************************************************
280 //**** DetectRoundChange pass
281 //*****************************************************************************
282 // To prevent any explicit change of the default rounding mode, this pass
283 // detects any call of the fesetround function.
284 // A warning is generated to ensure the user knows this has happened.
285 //
286 // Detects an erratum in UT699 LEON 3 processor
287 
288 char DetectRoundChange::ID = 0;
289 
291  : LEONMachineFunctionPass(tm, ID) {}
292 
295 
296  bool Modified = false;
297  for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
298  MachineBasicBlock &MBB = *MFI;
299  for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
300  MachineInstr &MI = *MBBI;
301  unsigned Opcode = MI.getOpcode();
302  if (Opcode == SP::CALL && MI.getNumOperands() > 0) {
303  MachineOperand &MO = MI.getOperand(0);
304 
305  if (MO.isGlobal()) {
306  StringRef FuncName = MO.getGlobal()->getName();
307  if (FuncName.compare_lower("fesetround") == 0) {
308  errs() << "Error: You are using the detectroundchange "
309  "option to detect rounding changes that will "
310  "cause LEON errata. The only way to fix this "
311  "is to remove the call to fesetround from "
312  "the source code.\n";
313  }
314  }
315  }
316  }
317  }
318 
319  return Modified;
320 }
321 
322 //*****************************************************************************
323 //**** FixAllFDIVSQRT pass
324 //*****************************************************************************
325 // This pass fixes the incorrectly working FDIVx and FSQRTx instructions that
326 // exist for some earlier versions of the LEON processor line. Five NOP
327 // instructions need to be inserted after these instructions to ensure the
328 // correct result is placed in the destination registers before they are used.
329 //
330 // This pass implements two fixes:
331 // 1) fixing the FSQRTS and FSQRTD instructions.
332 // 2) fixing the FDIVS and FDIVD instructions.
333 //
334 // FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in
335 // the pipeline when this option is enabled, so this pass needs only to deal
336 // with the changes that still need implementing for the "double" versions
337 // of these instructions.
338 //
339 char FixAllFDIVSQRT::ID = 0;
340 
342  : LEONMachineFunctionPass(tm, ID) {}
343 
347  DebugLoc DL = DebugLoc();
348 
349  bool Modified = false;
350  for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
351  MachineBasicBlock &MBB = *MFI;
352  for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
353  MachineInstr &MI = *MBBI;
354  unsigned Opcode = MI.getOpcode();
355 
356  // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is
357  // switched on so we don't need to check for them here. They will
358  // already have been converted to FSQRTD or FDIVD earlier in the
359  // pipeline.
360  if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) {
361  for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++)
362  BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
363 
364  MachineBasicBlock::iterator NMBBI = std::next(MBBI);
365  for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++)
366  BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
367 
368  Modified = true;
369  }
370  }
371  }
372 
373  return Modified;
374 }
LLVM_NODISCARD int compare_lower(StringRef RHS) const
compare_lower - Compare two strings, ignoring case.
Definition: StringRef.cpp:52
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
const GlobalValue * getGlobal() const
ReplaceFMULS(TargetMachine &tm)
Definition: LeonPasses.cpp:206
FixAllFDIVSQRT(TargetMachine &tm)
Definition: LeonPasses.cpp:341
static char ID
Definition: LeonPasses.h:49
InsertNOPLoad(TargetMachine &tm)
Definition: LeonPasses.cpp:75
A debug info location.
Definition: DebugLoc.h:34
const SparcInstrInfo * getInstrInfo() const override
DetectRoundChange(TargetMachine &tm)
Definition: LeonPasses.cpp:290
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:191
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
bool isPhysRegUsed(unsigned PhysReg) const
Return true if the specified register is modified or read in this function.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
DILocation * get() const
Get the underlying DILocation.
Definition: DebugLoc.cpp:21
const HexagonInstrInfo * TII
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
LEONMachineFunctionPass(TargetMachine &tm, char &ID)
Definition: LeonPasses.cpp:24
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition: LeonPasses.cpp:78
unsigned getNumOperands() const
Access to explicit operands of the instruction.
Definition: MachineInstr.h:277
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineBasicBlock * MBB
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:273
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
TargetInstrInfo - Interface to description of machine instruction set.
const SparcSubtarget * Subtarget
Definition: LeonPasses.h:27
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
int GetRegIndexForOperand(MachineInstr &MI, int OperandIndex)
Definition: LeonPasses.cpp:30
unsigned const MachineRegisterInfo * MRI
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition: LeonPasses.cpp:209
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:279
int getUnusedFPRegister(MachineRegisterInfo &MRI)
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:344
void markRegisterUsed(int registerIndex)
Definition: LeonPasses.h:41
static char ID
Definition: LeonPasses.h:63
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
Definition: MachineInstr.h:52
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition: LeonPasses.cpp:119
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition: LeonPasses.cpp:293
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
FixFSMULD(TargetMachine &tm)
Definition: LeonPasses.cpp:117
std::vector< int > UsedRegisters
Definition: LeonPasses.h:32
unsigned getReg() const
getReg - Returns the register number.
Primary interface to the complete machine description for the target machine.
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
static char ID
Definition: LeonPasses.h:75
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:783