]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/Sparc/LeonPasses.cpp
Merge llvm trunk r300422 and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / Sparc / LeonPasses.cpp
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"
14 #include "llvm/CodeGen/ISDOpcodes.h"
15 #include "llvm/CodeGen/MachineFunction.h"
16 #include "llvm/CodeGen/MachineInstr.h"
17 #include "llvm/CodeGen/MachineInstrBuilder.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
19 #include "llvm/IR/DiagnosticInfo.h"
20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/Support/raw_ostream.h"
22 using namespace llvm;
23
24 LEONMachineFunctionPass::LEONMachineFunctionPass(TargetMachine &tm, char &ID)
25     : MachineFunctionPass(ID) {}
26
27 LEONMachineFunctionPass::LEONMachineFunctionPass(char &ID)
28     : MachineFunctionPass(ID) {}
29
30 int LEONMachineFunctionPass::GetRegIndexForOperand(MachineInstr &MI,
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
52 int LEONMachineFunctionPass::getUnusedFPRegister(MachineRegisterInfo &MRI) {
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
75 InsertNOPLoad::InsertNOPLoad(TargetMachine &tm)
76     : LEONMachineFunctionPass(tm, ID) {}
77
78 bool InsertNOPLoad::runOnMachineFunction(MachineFunction &MF) {
79   Subtarget = &MF.getSubtarget<SparcSubtarget>();
80   const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
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
117 FixFSMULD::FixFSMULD(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {}
118
119 bool FixFSMULD::runOnMachineFunction(MachineFunction &MF) {
120   Subtarget = &MF.getSubtarget<SparcSubtarget>();
121   const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
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) {
146         clearUsedRegisterList();
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
206 ReplaceFMULS::ReplaceFMULS(TargetMachine &tm)
207     : LEONMachineFunctionPass(tm, ID) {}
208
209 bool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) {
210   Subtarget = &MF.getSubtarget<SparcSubtarget>();
211   const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
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) {
235         clearUsedRegisterList();
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
290 DetectRoundChange::DetectRoundChange(TargetMachine &tm)
291     : LEONMachineFunctionPass(tm, ID) {}
292
293 bool DetectRoundChange::runOnMachineFunction(MachineFunction &MF) {
294   Subtarget = &MF.getSubtarget<SparcSubtarget>();
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
341 FixAllFDIVSQRT::FixAllFDIVSQRT(TargetMachine &tm)
342     : LEONMachineFunctionPass(tm, ID) {}
343
344 bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) {
345   Subtarget = &MF.getSubtarget<SparcSubtarget>();
346   const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
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 }