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/LLVMContext.h"
20 #include "llvm/Support/raw_ostream.h"
21 using namespace llvm;
22 
23 LEONMachineFunctionPass::LEONMachineFunctionPass(TargetMachine &tm, char &ID)
24     : MachineFunctionPass(ID) {}
25 
26 LEONMachineFunctionPass::LEONMachineFunctionPass(char &ID)
27     : MachineFunctionPass(ID) {}
28 
29 int LEONMachineFunctionPass::GetRegIndexForOperand(MachineInstr &MI,
30                                                    int OperandIndex) {
31   if (MI.getNumOperands() > 0) {
32     if (OperandIndex == LAST_OPERAND) {
33       OperandIndex = MI.getNumOperands() - 1;
34     }
35 
36     if (MI.getNumOperands() > (unsigned)OperandIndex &&
37         MI.getOperand(OperandIndex).isReg()) {
38       return (int)MI.getOperand(OperandIndex).getReg();
39     }
40   }
41 
42   static int NotFoundIndex = -10;
43   // Return a different number each time to avoid any comparisons between the
44   // values returned.
45   NotFoundIndex -= 10;
46   return NotFoundIndex;
47 }
48 
49 // finds a new free FP register
50 // checks also the AllocatedRegisters vector
51 int LEONMachineFunctionPass::getUnusedFPRegister(MachineRegisterInfo &MRI) {
52   for (int RegisterIndex = SP::F0; RegisterIndex <= SP::F31; ++RegisterIndex) {
53     if (!MRI.isPhysRegUsed(RegisterIndex) &&
54         !is_contained(UsedRegisters, RegisterIndex)) {
55       return RegisterIndex;
56     }
57   }
58 
59   return -1;
60 }
61 
62 //*****************************************************************************
63 //**** InsertNOPLoad pass
64 //*****************************************************************************
65 // This pass fixes the incorrectly working Load instructions that exists for
66 // some earlier versions of the LEON processor line. NOP instructions must
67 // be inserted after the load instruction to ensure that the Load instruction
68 // behaves as expected for these processors.
69 //
70 // This pass inserts a NOP after any LD or LDF instruction.
71 //
72 char InsertNOPLoad::ID = 0;
73 
74 InsertNOPLoad::InsertNOPLoad(TargetMachine &tm)
75     : LEONMachineFunctionPass(tm, ID) {}
76 
77 bool InsertNOPLoad::runOnMachineFunction(MachineFunction &MF) {
78   Subtarget = &MF.getSubtarget<SparcSubtarget>();
79   const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
80   DebugLoc DL = DebugLoc();
81 
82   bool Modified = false;
83   for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
84     MachineBasicBlock &MBB = *MFI;
85     for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
86       MachineInstr &MI = *MBBI;
87       unsigned Opcode = MI.getOpcode();
88       if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) {
89         MachineBasicBlock::iterator NMBBI = std::next(MBBI);
90         BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
91         Modified = true;
92       }
93     }
94   }
95 
96   return Modified;
97 }
98 
99 //*****************************************************************************
100 //**** FixFSMULD pass
101 //*****************************************************************************
102 // This pass fixes the incorrectly working FSMULD instruction that exists for
103 // some earlier versions of the LEON processor line.
104 //
105 // The pass should convert the FSMULD operands to double precision in scratch
106 // registers, then calculate the result with the FMULD instruction. Therefore,
107 // the pass should replace operations of the form:
108 // fsmuld %f20,%f21,%f8
109 // with the sequence:
110 // fstod %f20,%f0
111 // fstod %f21,%f2
112 // fmuld %f0,%f2,%f8
113 //
114 char FixFSMULD::ID = 0;
115 
116 FixFSMULD::FixFSMULD(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {}
117 
118 bool FixFSMULD::runOnMachineFunction(MachineFunction &MF) {
119   Subtarget = &MF.getSubtarget<SparcSubtarget>();
120   const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
121   DebugLoc DL = DebugLoc();
122 
123   bool Modified = false;
124   for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
125     MachineBasicBlock &MBB = *MFI;
126     for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
127 
128       MachineInstr &MI = *MBBI;
129       unsigned Opcode = MI.getOpcode();
130 
131       const int UNASSIGNED_INDEX = -1;
132       int Reg1Index = UNASSIGNED_INDEX;
133       int Reg2Index = UNASSIGNED_INDEX;
134       int Reg3Index = UNASSIGNED_INDEX;
135 
136       if (Opcode == SP::FSMULD && MI.getNumOperands() == 3) {
137         // take the registers from fsmuld %f20,%f21,%f8
138         Reg1Index = MI.getOperand(0).getReg();
139         Reg2Index = MI.getOperand(1).getReg();
140         Reg3Index = MI.getOperand(2).getReg();
141       }
142 
143       if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
144           Reg3Index != UNASSIGNED_INDEX) {
145         clearUsedRegisterList();
146         MachineBasicBlock::iterator NMBBI = std::next(MBBI);
147         // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
148         markRegisterUsed(Reg3Index);
149         const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
150         markRegisterUsed(ScratchReg1Index);
151         const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
152         markRegisterUsed(ScratchReg2Index);
153 
154         if (ScratchReg1Index == UNASSIGNED_INDEX ||
155             ScratchReg2Index == UNASSIGNED_INDEX) {
156           errs() << "Cannot allocate free scratch registers for the FixFSMULD "
157                     "pass."
158                  << "\n";
159         } else {
160           // create fstod %f20,%f0
161           BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
162               .addReg(ScratchReg1Index)
163               .addReg(Reg1Index);
164 
165           // create fstod %f21,%f2
166           BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
167               .addReg(ScratchReg2Index)
168               .addReg(Reg2Index);
169 
170           // create fmuld %f0,%f2,%f8
171           BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
172               .addReg(Reg3Index)
173               .addReg(ScratchReg1Index)
174               .addReg(ScratchReg2Index);
175 
176           MI.eraseFromParent();
177           MBBI = NMBBI;
178 
179           Modified = true;
180         }
181       }
182     }
183   }
184 
185   return Modified;
186 }
187 
188 //*****************************************************************************
189 //**** ReplaceFMULS pass
190 //*****************************************************************************
191 // This pass fixes the incorrectly working FMULS instruction that exists for
192 // some earlier versions of the LEON processor line.
193 //
194 // This pass converts the FMULS operands to double precision in scratch
195 // registers, then calculates the result with the FMULD instruction.
196 // The pass should replace operations of the form:
197 // fmuls %f20,%f21,%f8
198 // with the sequence:
199 // fstod %f20,%f0
200 // fstod %f21,%f2
201 // fmuld %f0,%f2,%f8
202 //
203 char ReplaceFMULS::ID = 0;
204 
205 ReplaceFMULS::ReplaceFMULS(TargetMachine &tm)
206     : LEONMachineFunctionPass(tm, ID) {}
207 
208 bool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) {
209   Subtarget = &MF.getSubtarget<SparcSubtarget>();
210   const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
211   DebugLoc DL = DebugLoc();
212 
213   bool Modified = false;
214   for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
215     MachineBasicBlock &MBB = *MFI;
216     for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
217       MachineInstr &MI = *MBBI;
218       unsigned Opcode = MI.getOpcode();
219 
220       const int UNASSIGNED_INDEX = -1;
221       int Reg1Index = UNASSIGNED_INDEX;
222       int Reg2Index = UNASSIGNED_INDEX;
223       int Reg3Index = UNASSIGNED_INDEX;
224 
225       if (Opcode == SP::FMULS && MI.getNumOperands() == 3) {
226         // take the registers from fmuls %f20,%f21,%f8
227         Reg1Index = MI.getOperand(0).getReg();
228         Reg2Index = MI.getOperand(1).getReg();
229         Reg3Index = MI.getOperand(2).getReg();
230       }
231 
232       if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
233           Reg3Index != UNASSIGNED_INDEX) {
234         clearUsedRegisterList();
235         MachineBasicBlock::iterator NMBBI = std::next(MBBI);
236         // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
237         markRegisterUsed(Reg3Index);
238         const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
239         markRegisterUsed(ScratchReg1Index);
240         const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
241         markRegisterUsed(ScratchReg2Index);
242 
243         if (ScratchReg1Index == UNASSIGNED_INDEX ||
244             ScratchReg2Index == UNASSIGNED_INDEX) {
245           errs() << "Cannot allocate free scratch registers for the "
246                     "ReplaceFMULS pass."
247                  << "\n";
248         } else {
249           // create fstod %f20,%f0
250           BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
251               .addReg(ScratchReg1Index)
252               .addReg(Reg1Index);
253 
254           // create fstod %f21,%f2
255           BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
256               .addReg(ScratchReg2Index)
257               .addReg(Reg2Index);
258 
259           // create fmuld %f0,%f2,%f8
260           BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
261               .addReg(Reg3Index)
262               .addReg(ScratchReg1Index)
263               .addReg(ScratchReg2Index);
264 
265           MI.eraseFromParent();
266           MBBI = NMBBI;
267 
268           Modified = true;
269         }
270       }
271     }
272   }
273 
274   return Modified;
275 }
276 
277 //*****************************************************************************
278 //**** FixAllFDIVSQRT pass
279 //*****************************************************************************
280 // This pass fixes the incorrectly working FDIVx and FSQRTx instructions that
281 // exist for some earlier versions of the LEON processor line. Five NOP
282 // instructions need to be inserted after these instructions to ensure the
283 // correct result is placed in the destination registers before they are used.
284 //
285 // This pass implements two fixes:
286 //  1) fixing the FSQRTS and FSQRTD instructions.
287 //  2) fixing the FDIVS and FDIVD instructions.
288 //
289 // FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in
290 // the pipeline when this option is enabled, so this pass needs only to deal
291 // with the changes that still need implementing for the "double" versions
292 // of these instructions.
293 //
294 char FixAllFDIVSQRT::ID = 0;
295 
296 FixAllFDIVSQRT::FixAllFDIVSQRT(TargetMachine &tm)
297     : LEONMachineFunctionPass(tm, ID) {}
298 
299 bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) {
300   Subtarget = &MF.getSubtarget<SparcSubtarget>();
301   const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
302   DebugLoc DL = DebugLoc();
303 
304   bool Modified = false;
305   for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
306     MachineBasicBlock &MBB = *MFI;
307     for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
308       MachineInstr &MI = *MBBI;
309       unsigned Opcode = MI.getOpcode();
310 
311       // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is
312       // switched on so we don't need to check for them here. They will
313       // already have been converted to FSQRTD or FDIVD earlier in the
314       // pipeline.
315       if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) {
316         for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++)
317           BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
318 
319         MachineBasicBlock::iterator NMBBI = std::next(MBBI);
320         for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++)
321           BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
322 
323         Modified = true;
324       }
325     }
326   }
327 
328   return Modified;
329 }
330