1 //===------ LeonPasses.cpp - Define passes specific to LEON ---------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 //===----------------------------------------------------------------------===//
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"
24 LEONMachineFunctionPass::LEONMachineFunctionPass(TargetMachine &tm, char &ID)
25 : MachineFunctionPass(ID) {}
27 LEONMachineFunctionPass::LEONMachineFunctionPass(char &ID)
28 : MachineFunctionPass(ID) {}
30 int LEONMachineFunctionPass::GetRegIndexForOperand(MachineInstr &MI,
32 if (MI.getNumOperands() > 0) {
33 if (OperandIndex == LAST_OPERAND) {
34 OperandIndex = MI.getNumOperands() - 1;
37 if (MI.getNumOperands() > (unsigned)OperandIndex &&
38 MI.getOperand(OperandIndex).isReg()) {
39 return (int)MI.getOperand(OperandIndex).getReg();
43 static int NotFoundIndex = -10;
44 // Return a different number each time to avoid any comparisons between the
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)) {
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.
71 // This pass inserts a NOP after any LD or LDF instruction.
73 char InsertNOPLoad::ID = 0;
75 InsertNOPLoad::InsertNOPLoad(TargetMachine &tm)
76 : LEONMachineFunctionPass(tm, ID) {}
78 bool InsertNOPLoad::runOnMachineFunction(MachineFunction &MF) {
79 Subtarget = &MF.getSubtarget<SparcSubtarget>();
80 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
81 DebugLoc DL = DebugLoc();
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));
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.
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:
115 char FixFSMULD::ID = 0;
117 FixFSMULD::FixFSMULD(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {}
119 bool FixFSMULD::runOnMachineFunction(MachineFunction &MF) {
120 Subtarget = &MF.getSubtarget<SparcSubtarget>();
121 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
122 DebugLoc DL = DebugLoc();
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) {
129 MachineInstr &MI = *MBBI;
130 unsigned Opcode = MI.getOpcode();
132 const int UNASSIGNED_INDEX = -1;
133 int Reg1Index = UNASSIGNED_INDEX;
134 int Reg2Index = UNASSIGNED_INDEX;
135 int Reg3Index = UNASSIGNED_INDEX;
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();
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);
155 if (ScratchReg1Index == UNASSIGNED_INDEX ||
156 ScratchReg2Index == UNASSIGNED_INDEX) {
157 errs() << "Cannot allocate free scratch registers for the FixFSMULD "
161 // create fstod %f20,%f0
162 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
163 .addReg(ScratchReg1Index)
166 // create fstod %f21,%f2
167 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
168 .addReg(ScratchReg2Index)
171 // create fmuld %f0,%f2,%f8
172 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
174 .addReg(ScratchReg1Index)
175 .addReg(ScratchReg2Index);
177 MI.eraseFromParent();
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.
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:
204 char ReplaceFMULS::ID = 0;
206 ReplaceFMULS::ReplaceFMULS(TargetMachine &tm)
207 : LEONMachineFunctionPass(tm, ID) {}
209 bool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) {
210 Subtarget = &MF.getSubtarget<SparcSubtarget>();
211 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
212 DebugLoc DL = DebugLoc();
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();
221 const int UNASSIGNED_INDEX = -1;
222 int Reg1Index = UNASSIGNED_INDEX;
223 int Reg2Index = UNASSIGNED_INDEX;
224 int Reg3Index = UNASSIGNED_INDEX;
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();
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);
244 if (ScratchReg1Index == UNASSIGNED_INDEX ||
245 ScratchReg2Index == UNASSIGNED_INDEX) {
246 errs() << "Cannot allocate free scratch registers for the "
250 // create fstod %f20,%f0
251 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
252 .addReg(ScratchReg1Index)
255 // create fstod %f21,%f2
256 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
257 .addReg(ScratchReg2Index)
260 // create fmuld %f0,%f2,%f8
261 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
263 .addReg(ScratchReg1Index)
264 .addReg(ScratchReg2Index);
266 MI.eraseFromParent();
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.
286 // Detects an erratum in UT699 LEON 3 processor
288 char DetectRoundChange::ID = 0;
290 DetectRoundChange::DetectRoundChange(TargetMachine &tm)
291 : LEONMachineFunctionPass(tm, ID) {}
293 bool DetectRoundChange::runOnMachineFunction(MachineFunction &MF) {
294 Subtarget = &MF.getSubtarget<SparcSubtarget>();
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);
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";
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.
330 // This pass implements two fixes:
331 // 1) fixing the FSQRTS and FSQRTD instructions.
332 // 2) fixing the FDIVS and FDIVD instructions.
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.
339 char FixAllFDIVSQRT::ID = 0;
341 FixAllFDIVSQRT::FixAllFDIVSQRT(TargetMachine &tm)
342 : LEONMachineFunctionPass(tm, ID) {}
344 bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) {
345 Subtarget = &MF.getSubtarget<SparcSubtarget>();
346 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
347 DebugLoc DL = DebugLoc();
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();
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
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));
364 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
365 for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++)
366 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));